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
我想知道如何通过一个函数在分组的 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