Python Pandas:为什么numpy比Pandas的列分配要快得多?我可以进一步优化吗?

jfi*_*ive 7 python indexing numpy pandas

我正在通过将分类变量转换为二进制矩阵来预处理机器学习分类任务的数据,主要是使用pd.get_dummies().这适用于单个Pandas DataFrame列,并输出一个新的DataFrame,其行数与原始列中唯一数量的分类变量的原始和宽度相同.

我需要为形状的DataFrame完成这个:(3,000,000 x 16)它输出一个形状的二进制矩阵:(3,000,000 x 600).

在此过程中,转换为二进制矩阵的步骤pd.get_dummies()非常快,但使用输出矩阵的分配要慢得多pd.DataFrame.loc[].由于我必须切换到节电直到np.ndarray这是快,我只是想知道为什么?(请参阅问题底部的终端输出进行时间比较)

nb正如评论中指出的那样,我可以pd.get_dummies()在整个框架上完成所有工作.但是,有些列需要定制的预处理,即:放入存储桶.要处理的最难处理的列是一个包含一串标记的列(由,or 分隔,,必须像这样处理:df[col].str.replace(' ','').str.get_dummies(sep=',').此外,预处理的训练集和测试集需要相同的列集(继承自all_cols),因为它们可能一旦它们被分解成矩阵,就不具有相同的特征.

请参阅以下代码了解每个版本

DataFrame版本:

def preprocess_df(df):
    with open(PICKLE_PATH + 'cols.pkl', 'rb') as handle:
        cols = pickle.load(handle)

    x = np.zeros(shape=(len(df),len(cols)))
    # x = pd.DataFrame(columns=all_cols)

    for col in df.columns:
        # 1. make binary matrix
        df_col = pd.get_dummies(df[col], prefix=str(col))

        print "Processed: ", col,  datetime.datetime.now()

        # 2. assign each value in binary matrix to col in output
        for dummy_col in df_col.columns:
            x.loc[:, dummy_col] = df_col[dummy_col]

        print "Assigned: ", col,  datetime.datetime.now()

    return x.values
Run Code Online (Sandbox Code Playgroud)

np版本:

def preprocess_np(df):
    with open(PICKLE_PATH + 'cols.pkl', 'rb') as handle:
        cols = pickle.load(handle)

    x = np.zeros(shape=(len(df),len(cols)))

    for col in df.columns:
        # 1. make binary matrix
        df_col = pd.get_dummies(df[col], prefix=str(col))

        print "Processed: ", col,  datetime.datetime.now()

        # 2. assign each value in binary matrix to col in output
        for dummy_col in df_col.columns:
            idx = [i for i,j in enumerate(all_cols) if j == dummy_col][0]
            x[:, idx] = df_col[dummy_col].values.T

        print "Assigned: ", col,  datetime.datetime.now()

    return x
Run Code Online (Sandbox Code Playgroud)

定时输出(10,000示例)

DataFrame版本:

Processed:  Weekday 
Assigned:  Weekday 0.437081  
Processed:  Hour 0.002366
Assigned:  Hour 1.33815
Run Code Online (Sandbox Code Playgroud)

np版本:

Processed:  Weekday   
Assigned:  Weekday 0.006992
Processed:  Hour 0.002632
Assigned:  Hour 0.008989
Run Code Online (Sandbox Code Playgroud)

有没有不同的方法来进一步优化这个?我感兴趣的是,目前我正在放弃一个可能有用的功能,因为它太慢而无法处理额外的15,000列到输出.

关于我正在采取的方法的任何一般建议也表示赞赏!

谢谢

Cyr*_*rus 1

一项实验是改用x.loc[:, dummy_col] = df_col[dummy_col].values. 如果输入是一个系列,pandas 将检查每个分配的索引顺序。如果没有必要,使用 ndarray 进行分配会关闭它,这应该会提高性能。