快速高效 pandas groupby 求和运算
Fast and efficient pandas groupby sum operation
我有一个大约 1000 万行的巨大 lod 数据集,我在性能和速度方面存在巨大问题。我尝试使用 pandas
、numpy
(也使用 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
我可以使用以下不同的脚本来实现这一点。然而,在大数据集上,脚本非常慢。最后,我需要根据扩展输出计算所有用户之间的相关矩阵。这是输出结构的原因:
Pandas
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()
我希望我能证明我尝试了多种不同的可能性。但是,none 个选项对于如此多的行来说已经足够有效了。
我发现 似乎非常接近我的问题,但我无法将解决方案纳入我的问题。
非常感谢您的帮助!
通过结合有用的评论,我自己想出了一个解决方案。
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')
我有一个大约 1000 万行的巨大 lod 数据集,我在性能和速度方面存在巨大问题。我尝试使用 pandas
、numpy
(也使用 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
我可以使用以下不同的脚本来实现这一点。然而,在大数据集上,脚本非常慢。最后,我需要根据扩展输出计算所有用户之间的相关矩阵。这是输出结构的原因:
Pandas
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()
我希望我能证明我尝试了多种不同的可能性。但是,none 个选项对于如此多的行来说已经足够有效了。
我发现
非常感谢您的帮助!
通过结合有用的评论,我自己想出了一个解决方案。
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')