【问题标题】:Fast and efficient pandas groupby sum operation快速高效的 p​​andas groupby sum 运算
【发布时间】:2019-09-22 04:31:22
【问题描述】:

我有一个大约 1000 万行的庞大 lod 数据集,但在性能和速度方面存在很大问题。我尝试使用pandasnumpy(也使用numba 库)和dask。但是我没能取得足够的成功。

原始数据(最小和简化)

df = pd.read_csv('data.csv',sep=';', names=['ID', 'UserID'], error_bad_lines=False, 
     encoding='latin-1', dtype='category')

For problem reproduction:

df = pd.DataFrame({'ID': [999974708546523127, 999974708546523127, 999974708546520000], 'UserID': ['AU896', 'ZZ999', 'ZZ999']}, dtype='category')
df

ID                  UserID
999974708546523127  AU896  
999974708546523127  ZZ999
999974708546520000  ZZ999  

预期输出

User   999974708546520000   999974708546523127
AU896           1                     0            
ZZ999           1                     1    

我可以使用以下不同的脚本来实现这一点。然而,在大数据集上,脚本非常慢。最后,我需要根据扩展输出计算所有用户之间的相关矩阵。这是输出结构的原因:

熊猫

results_id = pd.crosstab(df.UserID, df.ID, dropna=False)

Numpy 和 Numba

import numpy as np
import numba

records = df.to_numpy()

unique_id =  np.unique(records[:, 0])
unique_userid = np.unique(records[:, 1])

results_id = np.zeros((len(unique_userid), len(unique_id)))

@numba.jit(nopython=True):
def ID_PreProcess(records, records_tcode, records_user):    
   for userid in range(len(unique_userid)):
        user = np.where(records[:, 1] == unique_userid[userid])

        for id in range(len(unique_id)):
            tcode_row= np.where(records[:, 0] == unique_id[id])
            inter = records[np.where((records[:,1] == id) * (records[:,0] == id))]
            results_id[userid, id]=len(inter)
   return results_id

results_id = ID_PreProcess(records, records_tcode, records_user)

黎明

import pandas as pd
import dask.dataframe as dd


dask_logs = dd.from_pandas(df, npartitions=2)
results_id = dd.concat([dask_logs.UserID ,dd.get_dummies(dask_logs.ID)],axis=1).groupby('UserID').sum().compute()

我希望我可以证明我尝试了多种不同的可能性。但是,对于如此多的行,没有一个选项足够有效。

我发现this post 似乎与我的问题非常接近,但我无法将解决方案整合到我的问题中。

非常感谢您的帮助!

【问题讨论】:

  • 有多少个独特的IDs?您是否真的需要将它们作为单独的列...将它们放在一个名为“ID”的列下并针对UserID 重复(或索引的一部分)是否有意义...否则你很可能是最终会得到一个非常稀疏的交叉表。
  • df.groupby(['UserID', 'ID']).size() 如何为您工作(或不工作?)
  • 试试上面的麦克...这将创建一个具有每个分组大小的多级索引...至少避免了稀疏性,并且可能更实用地索引/检索数据
  • 是的,最后我需要计算所有用户之间的相关矩阵。我可以从这个结果中做到吗?
  • @Mike_H 我仍然不确定你对pd.pivot 做了什么,所以不太确定对你有用的实际答案是什么......随意自我回答:)跨度>

标签: python pandas numpy dask numba


【解决方案1】:

通过合并有用的 cmets,我自己想出了一个解决方案。

df.groupby(['UserID', 'ID'], as_index=False).size()
df.reset_index(inplace = True)
df.columns = ['UserID', 'ID', 'Counter']
Expected_Output = pd.pivot('UserID', 'ID', 'Counter')

【讨论】:

  • 感谢迈克。我被同样的问题困扰着。 Dask 处理 groupby 计算非常脆弱。
猜你喜欢
  • 2022-01-26
  • 2012-12-05
  • 1970-01-01
  • 2018-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-29
  • 2022-01-21
相关资源
最近更新 更多