我有一个很大的csv,以这种形式每行有两个字符串:

g,k
a,h
c,i
j,e
d,i
i,h
b,b
d,d
i,a
d,h

我读了前两列,并将字符串重新编码为整数,如下所示:
import pandas as pd
df = pd.read_csv("test.csv", usecols=[0,1], prefix="ID_", header=None)
from sklearn.preprocessing import LabelEncoder

# Initialize the LabelEncoder.
le = LabelEncoder()
le.fit(df.values.flat)

# Convert to digits.
df = df.apply(le.transform)

这段代码来自https://stackoverflow.com/a/39419342/2179021

该代码工作得很好,但是当df大时速度很慢。我为每个步骤计时,结果令我惊讶。
  • pd.read_csv大约需要40秒。
  • le.fit(df.values.flat)大约需要30秒
  • df = df.apply(le.transform)大约需要250秒。

  • 有什么方法可以加快最后一步的速度吗?感觉这应该是所有人中最快的一步!

    在具有4GB RAM的计算机上进行记录步骤的更多时间

    maxymoo在下面的回答很快,但是没有给出正确的答案。以问题顶部的示例csv为例,将其转换为:
       0  1
    0  4  6
    1  0  4
    2  2  5
    3  6  3
    4  3  5
    5  5  4
    6  1  1
    7  3  2
    8  5  0
    9  3  4
    

    请注意,“d”在第一列中映射为3,但在第二列中映射为2。

    我尝试了从https://stackoverflow.com/a/39356398/2179021解决方案,并获得了以下信息。
    df = pd.DataFrame({'ID_0':np.random.randint(0,1000,1000000), 'ID_1':np.random.randint(0,1000,1000000)}).astype(str)
    df.info()
    memory usage: 7.6MB
    %timeit x = (df.stack().astype('category').cat.rename_categories(np.arange(len(df.stack().unique()))).unstack())
    1 loops, best of 3: 1.7 s per loop
    

    然后,我将数据框的大小增加了10倍。
    df = pd.DataFrame({'ID_0':np.random.randint(0,1000,10000000), 'ID_1':np.random.randint(0,1000,10000000)}).astype(str)
    df.info()
    memory usage: 76.3+ MB
    %timeit x = (df.stack().astype('category').cat.rename_categories(np.arange(len(df.stack().unique()))).unstack())
    MemoryError                               Traceback (most recent call last)
    

    这种方法似乎使用了太多的RAM来尝试转换相对较小的数据帧,从而导致崩溃。

    我还为LabelEncoder设置了具有1000万行的较大数据集的时间。它运行时不会崩溃,但仅合身线就花了50秒钟。 df.apply(le.transform)步骤耗时约80秒。

    我怎样才能:
  • 大致获得maxymoo的回答速度和LabelEncoder的大致内存使用情况,但是当数据帧具有两列时,这将给出正确的答案。
  • 存储映射,以便可以将其重用于其他数据(如LabelEncoder允许我执行的方式)吗?
  • 最佳答案

    看起来使用pandas category数据类型会更快。在内部,这使用哈希表,而LabelEncoder使用排序的搜索:

    In [87]: df = pd.DataFrame({'ID_0':np.random.randint(0,1000,1000000),
                                'ID_1':np.random.randint(0,1000,1000000)}).astype(str)
    
    In [88]: le.fit(df.values.flat)
             %time x = df.apply(le.transform)
    CPU times: user 6.28 s, sys: 48.9 ms, total: 6.33 s
    Wall time: 6.37 s
    
    In [89]: %time x = df.apply(lambda x: x.astype('category').cat.codes)
    CPU times: user 301 ms, sys: 28.6 ms, total: 330 ms
    Wall time: 331 ms
    

    编辑:这是您可以使用的自定义转换器类(您可能不会在scikit-learn官方发行版中看到此内容,因为维护者不希望将 Pandas 作为依赖项)
    import pandas as pd
    from pandas.core.nanops import unique1d
    from sklearn.base import BaseEstimator, TransformerMixin
    
    class PandasLabelEncoder(BaseEstimator, TransformerMixin):
        def fit(self, y):
            self.classes_ = unique1d(y)
            return self
    
        def transform(self, y):
            s = pd.Series(y).astype('category', categories=self.classes_)
            return s.cat.codes
    

    关于python - 如何加快LabelEncoder将类别变量重新编码为整数的速度,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39475187/

    10-12 21:58