繁体   English   中英

如何提高对熊猫数据框的聚合操作的速度?

[英]How to improve the speed of an aggregate operation on a pandas dataframe?

我有一个名为data_1的熊猫数据data_1如下所示:

tenant_id  tenant_class_id tenant_date
100         10001           2004-01-10
100         10001           2004-08-25
101         10001           2016-09-20
102         10002           2013-07-12
103         10003           2011-04-05
103         10004           2002-05-05
103         10003           2003-12-26

我的目标是要找到最早/第一tenant_date每个tenant_id tenant_idlong格式, tenant_datedatetime64格式

我使用以下代码进行计算:

output = data_1.groupby(['tenant_id']).apply(lambda x: x.nsmallest(1, 'tenant_date')).reset_index(drop=1)

这对于较小的数据集来说效果很好,但是我的data_1包含约2亿行。 此代码永远不会完成。 我有大约244 GB RAM的足够内存。 有没有更有效的方法来快速执行此操作?

您可以尝试sort_values + drop_duplicates

output = data_1.sort_values(['tenant_id','tenant_date']).drop_duplicates(['tenant_id'])

sort_values + GroupBy.head

output = data_1.sort_values(['tenant_id','tenant_date']).groupby(['tenant_id']).head(1)

或者通过idxmin查看每组最小索引:

output = data_1.loc[data_1.groupby(['tenant_id'])['tenant_date'].idxmin()]

要么:

output = data_1.set_index(['tenant_class_id'])
               .groupby(['tenant_id'])['tenant_date'].nsmallest(1).reset_index()

时间

np.random.seed(123)
N = 1000000
L = pd.date_range('2015-01-01', '2018-01-01')

df = pd.DataFrame({'tenant_date': np.random.choice(L, size=N),
                   'tenant_id':np.random.randint(1000,size=N),
                   'tenant_class_id':np.random.randint(1000,size=N)})
print (df)

In [99]: %timeit data_1.sort_values(['tenant_id','tenant_date']).drop_duplicates(['tenant_id'])
1000 loops, best of 3: 1.97 ms per loop

In [100]: %timeit data_1.sort_values(['tenant_id','tenant_date']).groupby(['tenant_id']).head(1)
1000 loops, best of 3: 2.07 ms per loop

In [101]: %timeit data_1.loc[data_1.groupby(['tenant_id'])['tenant_date'].idxmin()]
100 loops, best of 3: 2.04 ms per loop

In [102]: %timeit data_1.set_index(['tenant_class_id']).groupby(['tenant_id'])['tenant_date'].nsmallest(1).reset_index()
100 loops, best of 3: 8.64 ms per loop

In [103]: %timeit data_1.groupby(['tenant_id']).apply(lambda x: x.nsmallest(1, 'tenant_date')).reset_index(drop=1)
100 loops, best of 3: 11.4 ms per loop

警告

给定组数,结果不能解决性能问题,这对于其中一些解决方案的时序会产生很大影响。

排序然后使用drop_duplicates 但是请确保首先将日期列转换为日期时间。

df['tenant_date'] = pd.to_datetime(df['tenant_date'])
df.sort_values(['tenant_id', 'tenant_date']).drop_duplicates('tenant_id')

   tenant_id  tenant_class_id tenant_date
0        100            10001  2004-01-10
2        101            10001  2016-09-20
3        102            10002  2013-07-12
5        103            10004  2002-05-05

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM