首页 > 解决方案 > 聚合行和列的慢循环

问题描述

我有一个 DataFrame,其中有一列名为“UserNbr”,一列名为“Spclty”,它由以下元素组成:

[['104', '2010-01-31'], ['215', '2014-11-21'], ['352', '2016-07-13']]

列表中可以有 0 个或多个元素。

一些 UserNbr 键出现在多行中,我希望将每个这样的组折叠成一行,以便“Spclty”包含所有唯一的字典,就像上面显示的列表中的字典一样。

为了节省附加到 DataFrame 的开销,我将每个输出行附加到一个列表,而不是附加到 DataFrame。

我的代码正在运行,但在 0.7M 行输入上运行需要数小时。(实际上,我从来没有让我的笔记本电脑打开足够长的时间让它完成执行。)

有没有更好的方法来聚合成这样的结构,也许使用提供更多数据重塑选项的库而不是循环遍历 UserNbr?(在 R 中,我会使用 data.table 和 dplyr 库。)

# loop over all UserNbr: 
#   consolidate specialty fields into dict-like sets (to remove redundant codes);
#   output one row per user to new data frame
out_rows = list() 
spcltycol = df_tmp.column.get_loc('Spclty')                
all_UserNbr = df_tmp['UserNbr'].unique()
for user in all_UserNbr:
    df_user = df_tmp.loc[df_tmp['UserNbr'] == user]
    if df_user.shape[0] > 0:   
        open_combined = df_user_open.iloc[0, spcltycol]   # capture 1st row
        for row in range(1, df_user.shape[0]):       # union with any subsequent rows
            open_combined = open_combined.union(df_user.iloc[row, spcltycol])
        new_row = df_user.drop(['Spclty', 'StartDt'], axis = 1).iloc[0].tolist()
        new_row.append(open_combined)
        out_rows.append(new_row)

# construct new dataframe with no redundant UserID rows:
df_out = pd.DataFrame(out_rows, 
                      columns = ['UserNbr', 'Spclty'])
# convert Spclty sets to dicts:
df_out['Spclty'] = [dict(df_out['Spclty'][row]) for row in range(df_out.shape[0])]

到 dict 的转换消除了行之间重复的特性,在输出中,Spclty 值应如下所示:

{'104': '2010-01-31', '215': '2014-11-21', '352': '2016-07-13'}

除了可能存在比任何相应输入行中更多的键值对(由对 UserNbr 的聚合产生)。

标签: python-3.xpandas

解决方案


我撤回这个问题。

我曾希望有一种有效的方法将 groupby 与其他东西一起使用,但我还没有找到任何具有像这样的复杂数据结构的示例,也没有得到任何指导。

对于那些在 Python 中遇到类似的非常缓慢的聚合问题的人,我建议加紧使用 PySpark。我现在正在使用 Databricks 笔记本解决这个问题,并且正在使用 pyspark.sql.window Window 函数取得进展。(现在,运行测试只需几分钟而不是几小时!)

部分解决方案在此处的答案中:

PySpark list() in withColumn() 只工作一次,那么 AssertionError: col 应该是 Column


推荐阅读