Pandas 使用除法按聚合分组

Pandas group by aggregate using division

我想知道如何通过一个函数在分组的 pandas 数据框中聚合数据,在该函数中我考虑了数据框某些列中存储的值。这在操作顺序很重要的操作中很有用,例如除法。

例如我有:

In [8]: df
Out[8]: 
  class cat  xer
0     a   1    2
1     b   1    4
2     c   1    9
3     a   2    6
4     b   2    8
5     c   2    3

我想按 class 分组,并且对于每个 class,将 cat == 1 对应的 xer 值除以 cat == 2 对应的值。换句话说,最终输出中的条目应该是:

  class    div
0     a   0.33  (i.e. 2/6)
1     b    0.5  (i.e. 4/8)
2     c      3  (i.e. 9/3)

这可以使用 groupby 来实现吗?如果不手动遍历每个 class ,我无法完全弄清楚如何去做,即使这样它也不干净或有趣。

不用太聪明:

In [11]: one = df[df["cat"] == 1].set_index("class")["xer"]

In [12]: two = df[df["cat"] == 2].set_index("class")["xer"]

In [13]: one / two
Out[13]:
class
a    0.333333
b    0.500000
c    3.000000
Name: xer, dtype: float64

鉴于您的 DataFrame,您可以使用以下内容:

df.groupby('class').agg({'xer': lambda L: reduce(pd.np.divide, L)})

这给你:

            xer
class          
a      0.333333
b      0.500000
c      3.000000

这适合每组 > 2 个(如果需要的话),但您可能希望确保您的 df 首先按 cat 排序,以确保它们以正确的顺序出现。

这是一种方法,一步一步:

# get cat==1 and cat==2 merged by class
grouped = df[df.cat==1].merge(df[df.cat==2], on='class')
# calculate div
grouped['div'] = grouped.xer_x / grouped.xer_y
# return the final dataframe
grouped[['class', 'div']]

产生:

  class       div
0     a  0.333333
1     b  0.500000
2     c  3.000000

您可能希望重新排列数据以便于查看:

df2 = df.set_index(['class', 'cat']).unstack()

>>> df2
       xer   
cat      1  2
class        
a        2  6
b        4  8
c        9  3

然后您可以执行以下操作以获得您想要的结果:

>>> df2.iloc[:,0].div(df2.iloc[:, 1])

class
a        0.333333
b        0.500000
c        3.000000
Name: (xer, 1), dtype: float64