python - pandas使用groupby加速多行计算

标签 python pandas dataframe pandas-groupby

我正在尝试对数据框中的每一行进行多行计算。

我当前的解决方案需要近 2 小时才能处理 200k 行。所以效率很低,我希望 groupby 或其他一些 pandas 方法可以在这里帮助我。

例如,我的数据如下所示(您现在可以忽略日期):

id group start_date end_date   three_yrs_ago_date days_missing
01 23    2005-01-01 2006-01-01 2002-01-01           1
02 23    2006-01-06 2007-01-06 2003-01-06           6
03 23    2007-01-15 2008-01-15 2004-01-15           9
07 17    2014-01-01 2015-02-01 2011-01-01           2
07 23    2015-01-01 2016-02-01 2012-01-01           4

所以这里的目标是按group编号对所有内容进行分组,然后将该组中最近 3 年内发生的所有其他行的所有 days_missing 相加年。也就是说,其他行 start_date 位于当前行的 third_yrs_ago_date 或之后,以及当前行的 end_date 或之前。

这有点拗口,但它基本上是三个标准。这样,如果这是整个数据集,我们会得到这个结果(删除日期列):

id group days_missing days_missing_in_last_three_years            
01 23    1            1    # no change: no prior years
02 23    6            7 
03 23    9            16  
07 17    2            2    # no change: only member of it's group
07 23    4            4    # no change: other group members more than 3 years ago

我将向您展示我当前拥有的代码,但速度很慢。

我逐行浏览数据帧,创建一个包含所有组成员的临时数据帧,然后将这些组成员缩减为仅符合日期标准的成员。这并不漂亮:

days=[]
for index, row in tqdm(df.iterrows()):
    # moderately slow (~2 hour):
    temp = df[df['group'] == row['group']]
    temp = temp[temp['start_date'] >= row['three_yrs_ago_date']]
    temp = temp[temp['end_date'] <= row['start_date']]
    add = temp['days_missing'].sum() + row['days_missing']
    days.append(add)
df['days_missing_in_last_three_years'] = days

我尝试了其他两种方法,但都没有成功:

# very slow (~3 hours):
cov.append(df[(df['group'] == row['group']) & (df['start_date'] >= row['three_yrs_ago_date']) & (df['end_date'] <= row['start_date'])]['days_missing'].sum()+row['days_missing'])

# doesn't work - incorrect use of groupby
df['test'] = df[(df.groupby(['group'])['start_date'] >= df.groupby(['group'])['three_yrs_ago_date']) & (df.groupby(['group'])['end_date'] <= df.groupby(['group'])['start_date'])]['days_missing'].sum()

是否有比将其分解为较小的临时数据帧并对其进行计算更有效的更好方法?

最佳答案

这是一种解决方案,可能比您的方法更快。在 df.groupby('group') 上使用循环 for,然后在每个分组数据报 df_gapply。您可以使用 Between 方法来选择每行两个日期之间的 df_g 部分

for name, df_g in df.groupby('group'):
    df.loc[df_g.index,'test'] = df_g.apply(lambda row: (df_g['days_missing'][df_g['start_date']
                                                           .between(row['three_yrs_ago_date'], row['end_date'])].sum()),1)
df['test'] = df['test'].astype(int) #to get integer

结果如预期:

   id  group start_date   end_date three_yrs_ago_date  days_missing  test
0   1     23 2005-01-01 2006-01-01         2002-01-01             1     1
1   2     23 2006-01-06 2007-01-06         2003-01-06             6     7
2   3     23 2007-01-15 2008-01-15         2004-01-15             9    16
3   7     17 2014-01-01 2015-02-01         2011-01-01             2     2
4   7     23 2015-01-01 2016-02-01         2012-01-01             4     4

编辑:使用numpy函数更快的方法:

import numpy as np
for name, df_g in df.groupby('group'):
    m_g = ( np.less_equal.outer(df_g['three_yrs_ago_date'], df_g['start_date']) 
            & np.greater_equal.outer(df_g['end_date'], df_g['start_date']) )
    df.loc[df_g.index,'test'] =np.dot(m_g, df_g['days_missing'])
df['test'] = df['test'].astype(int) #to get integer

关于python - pandas使用groupby加速多行计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50935098/

相关文章:

python - 将 tf.data.Dataset 包装到 tf.function 中是否可以提高性能?

python - Pandas:列和索引之间的多索引应用功能

r - 从三个数据框中一一组合列

python - python vs numpy中的 boolean 和类型检查

python - 为什么 groupby sum 不将 boolean 转换为 int 或 float?

python - ValueError : The truth value of a Series is ambiguous. 使用 a.empty、a.bool()、a.item()、a.any() 或 a.all():返回具有空值的列

python - 填充具有多个系列的 pandas 数据框的缺失日期

python - 使用 Python,如何按小时对 Dataframe 中的列进行分组?

r - 将连续日期的行转换为日期范围的列

python - 为什么我可以从终端运行此命令,但当我的 python 从终端为我运行它时却收到错误?