Python 利用100万条记录分组使用熊猫的有效方法
我有一个数据帧,可以使用下面的代码生成Python 利用100万条记录分组使用熊猫的有效方法,python,python-3.x,pandas,dataframe,pandas-groupby,Python,Python 3.x,Pandas,Dataframe,Pandas Groupby,我有一个数据帧,可以使用下面的代码生成 df2 = pd.DataFrame({'subject_ID':[1,1,1,1,1,1,2,2,2,2],'colum' : ['L1CreaDate','L1Crea','L2CreaDate','L2Crea','L3CreaDate','L3Crea','L1CreaDate','L1Crea','L2CreaDate','L2Crea'], 'dates':['2016-10-30 00:00:00',2.3,
df2 = pd.DataFrame({'subject_ID':[1,1,1,1,1,1,2,2,2,2],'colum' : ['L1CreaDate','L1Crea','L2CreaDate','L2Crea','L3CreaDate','L3Crea','L1CreaDate','L1Crea','L2CreaDate','L2Crea'],
'dates':['2016-10-30 00:00:00',2.3,'2016-10-30 00:00:00',2.5,np.nan,np.nan,'2016-10-30 00:00:00',12.3,'2016-10-30 00:00:00',12.3]})
我试图在上面的数据帧上执行以下操作。虽然代码工作得非常好,但问题是当我使用groupby语句时。它在示例数据帧中速度很快,但在具有100多万条记录的实际数据中,它需要一段时间,而且运行时间很长
df2['col2'] = df2['colum'].str.split("Date").str[0]
df2['col3'] = df2['col2'].str.extract('(\d+)', expand=True).astype(int)
df2 = df2.sort_values(by=['subject_ID','col3'])
df2['count'] = df2.groupby(['subject_ID','col2'])['dates'].transform(pd.Series.count)
我使用groupby
获得下面的输出count
列,这样我就可以拒绝count为0
的记录。放弃NA是有逻辑的。这不仅仅是放弃所有的NA。如果你想知道这一点,请参考这篇文章
在实际数据中,一个人可能有超过10000行。因此,单个数据帧有超过100万行
有没有其他更好更有效的方法来执行groupby
或获取count
列
思想是使用列表理解和拆分
来提高性能,然后不将输出分配给新列计数
,而是使用提取的整数进行过滤和最后排序:
df2['col2'] = [x.split("Date")[0] for x in df2['colum']]
df2 = df2[df2.groupby(['subject_ID','col2'])['dates'].transform('count').ne(0)].copy()
df2['col3'] = df2['col2'].str.extract('(\d+)', expand=True).astype(int)
df2 = df2.sort_values(by=['subject_ID','col3'])
print (df2)
subject_ID colum dates col2 col3
0 1 L1CreaDate 2016-10-30 00:00:00 L1Crea 1
1 1 L1Crea 2.3 L1Crea 1
2 1 L2CreaDate 2016-10-30 00:00:00 L2Crea 2
3 1 L2Crea 2.5 L2Crea 2
6 2 L1CreaDate 2016-10-30 00:00:00 L1Crea 1
7 2 L1Crea 12.3 L1Crea 1
8 2 L2CreaDate 2016-10-30 00:00:00 L2Crea 2
9 2 L2Crea 12.3 L2Crea 2
如果获取错误:
AttributeError:“float”对象没有属性“split”
这意味着可能缺少值,因此应更改列表理解:
df2['col2'] = [x.split("Date")[0] if x == x else np.nan for x in df2['colum']]
检查性能:
def new(df2):
df2['col2'] = [x.split("Date")[0] for x in df2['colum']]
df2 = df2[df2.groupby(['subject_ID','col2'])['dates'].transform('count').ne(0)].copy()
df2['col3'] = df2['col2'].str.extract('(\d+)', expand=True).astype(int)
return df2.sort_values(by=['subject_ID','col3'])
def orig(df2):
df2['col2'] = df2['colum'].str.split("Date").str[0]
df2['col3'] = df2['col2'].str.extract('(\d+)', expand=True).astype(int)
df2 = df2.sort_values(by=['subject_ID','col3'])
df2['count'] = df2.groupby(['subject_ID','col2'])['dates'].transform(pd.Series.count)
return df2[df2['count'].ne(0)]
In [195]: %timeit (orig(df2))
10.8 ms ± 728 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [196]: %timeit (new(df2))
6.11 ms ± 144 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
我现在就试试。感谢您的回复。能在jupyter笔记本中找到每个单元格的执行时间吗?当我使用%timeit
,它不会返回anything@AVLES-嗯,试试自定义函数,给我一些时间来解决问题。你的解决方案在性能上比我的好,你的Python知识很棒,令人钦佩。你们在论坛上的回答让我受益匪浅。谢谢你,我只是提个简单的问题。建议使用.copy()
函数,而不仅仅是分配给新的数据帧。例如:df3=df2.copy()
推荐/快于df3=df2