Groupby在Pandas中的变异性能

时间:2017-07-31 14:00:49

标签: pandas numpy

我经常发现自己试图做出等同于groupby然后mutate的R等等,但很多人都指出只使用groupbyapply受到主要影响性能问题。所以我的问题是,根据该组中的某些条件,在pandas中对数据帧进行分组的最佳方法是什么,根据某些计算添加新列?

我已经搜索过并且没有找到任何关于如何使用numpy在pandas中矢量化自定义函数的指南/步骤。所有类似问题的答案都是针对用户的,并且不能很好地概括。

编辑:澄清问题功能并添加玩具数据

df
Out[17]: 
             ID   ID2        col1        col2       col3    value
0             1     J       333.5       333.3      333.4      cat    
1             1     S       333.5       333.3      333.8      
2             2     J       333.7       333.3      333.8      cat
3             2     S       333.7       333.3      333.4      dog
4             3     L       333.7       333.8      333.9      
5             3     D       333.8       333.8      333.9      
6             4     S       333.8       333.6      333.7      cat
7             4     J       333.8       333.2      333.8      
8             4     J       333.8       333.7      333.9      
9             4     L       333.8       333.3      333.4      cat

以下是一些例子,我经常遇到:

  1. 示例一,根据条件将功能应用于组,使用原始数据帧返回结果。
  2. df.groupby(by=['ID']).apply(myfunc)

    def myfunc(group):
        group['new_col'] = len(group.query('''ID2=='T' & (col1>=col3 | px<=col2)''').unique())
        return group
    
    1. 与上一个示例类似,但现在我只想根据某些条件更新现有列,然后使用原始数据帧返回结果。
    2. df.groupby(by=['ID']).apply(update_func)

      def update_func(group):
           if 'S' in group['ID2'].values:
                group.loc[(group['value']=='cat'), 'other_column'] = False
           return group
      

2 个答案:

答案 0 :(得分:1)

我认为您不需要在groupby中进行屏蔽,让我们看看这是否适用于您。

d1 = df.assign(mask=np.logical_and(df.ID2 == 'J', (np.logical_or((df.col1 >= df.col3), (df.col1 <= df.col2)))))

dict = d1.groupby('ID').apply(lambda x: x.loc[x['mask'],'col1'].size).to_dict()

答案 1 :(得分:0)

对于第一个示例,我使用numpy运算符改进了函数,并且建议使用@ScottBoston,我更改了函数以仅返回值,然后将它们映射回原始数据帧:

def my_func(group):
    mask = np.logical_and(group.ID2 == 'J', (np.logical_or((group.col1 >= group.col3), (group.col1 <= group.col2))))
    return len(group[mask].col1.unique())

dict = df.groupby(by=['ID'], sort=False).apply(my_func).to_dict() #This is a bit slow

df['new_col'] = df['ID'].map(dict) #This is fast

最慢的部分仍然是必须对每个组进行操作的numpy条件的应用。如果有一种方法可以对每一个并行操作,那么这将是理想的,因为不需要像现在那样按顺序进行操作。