2017-07-31 80 views
0

GROUPBY变异性能我经常发现自己想要做将R相当于groupby然后mutate,但很多人都指出只需使用groupbyapply患有重大的性能问题。所以我的问题是,什么是在pandas中分组数据框的最佳方式,然后根据该组中的某些条件添加一个基于某些计算的新列?在熊猫

我已搜索和搜索,我还没有找到任何关于如何矢量化使用numpy的熊猫自定义函数的指南/步骤。对类似问题的所有答案总是特定于用户,并且不能很好地概括。

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

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. 实施例之一,应用功能基于条件,返回组用原始数据框返回结果。

df.groupby(by=['ID']).apply(myfunc)

def myfunc(group): 
    group['new_col'] = len(group.query('''ID2=='T' & (col1>=col3 | px<=col2)''').unique()) 
    return group 
  • 类似于前面的例子,但现在我只希望基于一些条件来更新现有的列,然后返回回来的结果原始数据帧。
  • 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 
    
    +0

    你有什么具体的例子吗?这是一个开放式的问题,在这个论坛上被认为是广泛的。 –

    +0

    @ScottBoston我发表了一些例子,它们在当前形式中是否过于宽泛? – guy

    +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() 
    
    +0

    看起来更快,但运行%timeit发出了以下消息: '最慢的运行比最快的运行长26.13倍。这可能意味着正在缓存中间结果。' '1循环,最好的3:每循环4.02秒' – guy

    +0

    没关系,当我重新运行它时,它没有给出任何奇怪的消息。如果你对第二个例子有类似的策略,请告诉我!谢谢:) – guy

    +1

    seoncd策略已列在上述问题的评论中。尝试这种说法。 –

    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条件具有用于对每个组进行操作。如果有一种方法可以并行操作,那么这将是理想的,因为不需要按照现在的顺序进行操作。