2017-08-10 82 views
1

我有以下形式的熊猫数据帧:熊猫GROUPBY和广播结果原来的数据帧

 bowler inning wickets Total_wickets matches balls 
0 SL Malinga  1  69   143   44 4078 
1 SL Malinga  2  74   143   54 4735 
2 A Mishra  1  48   124   50 3908 
3 A Mishra  2  76   124   62 4930 
4 DJ Bravo  1  61   122   48 3887 

我想GROUPBY上“投球手”和“局”这个DF和执行在'wickets'和'balls'列上进行一些计算,然后将它广播到与新列相同的df。 的方法之一,我尝试是使用的变换,例如:

df_bowler['strike rate'] = df_bowler.groupby(['bowler','inning']).transform(lambda x : x['balls']/x['wickets']) 

这导致KeyError异常例外:

KeyError: ('balls', 'occurred at index wickets')

我完成我需要的东西,通过使用应用],然后合并,例如:

df_strRate = df_bowler.groupby(['bowler','inning']).apply(lambda x:x['balls']/x['wickets']).reset_index(level=2,drop=True).reset_index(name='strike rate') 
df_bowler = df_bowler.merge(df_strRate,on=['bowler','inning']) 

但是,这似乎是一个迂回的做法。我想知道为什么变换在这种情况下失败。任何指针?

谢谢。

回答

2

您的变换失败了,因为您正沿着错误轴应用它,并且您需要首先使用聚合,例如sum()。检查了这一点:

In [83]: df.groupby(['bowler', 'inning']).sum().transform(lambda x : x['balls'].astype(float)/x['wickets'].astype(float), axis=1) 
Out[83]: 
bowler  inning 
A Mishra 1   81.416667 
      2   64.868421 
DJ Bravo 1   63.721311 
SL Malinga 1   59.101449 
      2   63.986486 
dtype: float64 

但你不妨这样做:

In [88]: df['strike_rate'] = df.balls/df.wickets 
In [89]: df 
Out[89]: 
     bowler inning wickets Total_wickets matches balls strike_rate 
0 SL Malinga  1  69   143  44 4078 59.101449 
1 SL Malinga  2  74   143  54 4735 63.986486 
2 A Mishra  1  48   124  50 3908 81.416667 
3 A Mishra  2  76   124  62 4930 64.868421 
4 DJ Bravo  1  61   122  48 3887 63.721311 
+0

我认为你是错的 - 你的变换并不['GroupBy.transform'(HTTP://大熊猫。 pydata.org/pandas-docs/stable/generated/pandas.core.groupby.GroupBy.transform.html),但['DataFrame.transform'](http://pandas.pydata.org/pandas-docs/stable/ generated/pandas.DataFrame.transform.html),因为汇总'sum'后会得到另一个数据帧。 – jezrael

+0

我明白了为什么我的初始转换失败了,谢谢。但是,我无法让您的转换解决方案正常工作。变形时我得到一个attributeError。 – Tontodoin

+0

我不得不看到那个回溯。我只是再试一次,我不必做任何特别的事情,它仍然有效。检查你的df。keys()' –

0

编辑:

使用适用()

df = df.merge(df.groupby(['bowler', 'inning']).apply(lambda x : sum(x['balls']/x['wickets')]).reset_index(), on=['bowler', 'inning']).rename(columns={0:'Mycolumn'}) 
#If you don't want a rename then new resulted column will be named as 0. As per your wish, use it/discard rename part. 

试试下面的方法或者,如果你想要简单的列操作,我更喜欢Cory的第二选项。

1

有问题GroupBy.transform功能如果不是在[]定义的列第一与每个Series分开工作 - 所以不能用2列一起工作,不可能将它们划分:

def f(x): 
    print (x) 

2 48 
Name: wickets, dtype: int64 
2 124 
Name: Total_wickets, dtype: int64 
2 50 
Name: matches, dtype: int64 
2 3908 
Name: balls, dtype: int64 

df = df_bowler.groupby(['bowler','inning']).transform(f) 

如果[]定义列

def f(x): 
    print (x) 

2 3908 
Name: (A Mishra, 1), dtype: int64 
3 4930 
Name: (A Mishra, 2), dtype: int64 
4 3887 
Name: (DJ Bravo, 1), dtype: int64 
0 4078 
Name: (SL Malinga, 1), dtype: int64 
1 4735 
Name: (SL Malinga, 2), dtype: int64 


df = df_bowler.groupby(['bowler','inning'])['balls'].transform(f) 

同样的工作方式DataFrameGroupBy.agg功能。

结论:

如果想组处理数据需要GroupBy.apply

def f(x): 
    print (x) 

    bowler inning wickets Total_wickets matches balls 
2 A Mishra  1  48   124  50 3908 
    bowler inning wickets Total_wickets matches balls 
2 A Mishra  1  48   124  50 3908 
    bowler inning wickets Total_wickets matches balls 
3 A Mishra  2  76   124  62 4930 
    bowler inning wickets Total_wickets matches balls 


df = df_bowler.groupby(['bowler','inning']).apply(f) 
+0

这个总结非常有用。谢谢! – Tontodoin