我有一个名为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_id
找到最早/第一个tenant_date
。tenant_id
采用long
格式,tenant_date
采用datetime64
格式
我使用此代码进行计算:
output = data_1.groupby(['tenant_id']).apply(lambda x: x.nsmallest(1, 'tenant_date')).reset_index(drop=1)
这对于较小的数据集非常有效,但我的data_1
包含大约 2 亿行。此代码永远不会完成。我有足够的内存和大约 244 GB 的 RAM。 有没有更有效的方法来快速完成此操作?
排序然后使用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
你可以试试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
警告
考虑到组的数量,结果没有解决性能问题,这将对其中一些解决方案的时间产生很大影响。