value_counts和分组归一化

时间:2018-12-14 20:06:18

标签: pandas pandas-groupby

我有这个数据框:

Name  |  Survey_A |  Survey_B
----------------------------
A     |  y        |  z
A     |  z        |  z
A     |  y        |  y
B     |  z        |  y
B     |  z        |  y
B     |  y        |  z

我想在Survey_A和Survey_B中获得按名称分组的每种类型的标准化值计数。

我知道如何使用agg函数获取value_counts:

(df
   .groupby('Name')
   .agg({i:'value_counts' for i in
     df[['Survey_A', 'Survey_B']]})

给出:

Name  |  type  |  Survey_A |  Survey_B
--------------------------------------
A     |  y     |  2        | 1
      |  z     |  1        | 2
B     |  y     |  1        | 2
      |  z     |  2        | 1

但是我不知道如何像使用value_counts一样获得标准化的pandas.Series.value_counts(normalize=True)

我知道如何在一列上做到这一点:

(df
  .groupby('Name')['Survey_A']
  .value_counts(normalize=True))

哪个给:

Name  |  type  |  Survey_A
--------------------------
A     |  y     |  0.666     
      |  z     |  0.333  
B     |  y     |  0.333   
      |  z     |  0.666    

但不是几个。我尝试过:

(df
   .groupby('Name')
   .agg({i: lambda x:      
     x.value_counts(normalize=true) for i 
     in df[['Survey_A', 'Survey_B']]}))

但没有成功

使用这样的自定义功能是可能的:

def get_pct(g):
    output = pd.DataFrame()
    for c in g[['Survey_A', 'Survey_B']]:
        output[c] = g[c].value_counts(normalize=True)
    return output

df.groupby('Name').apply(get_pct)

但是我想知道是否还有其他的熊猫方法...

2 个答案:

答案 0 :(得分:0)

您可以使用:

df.groupby('x').agg({'Survey_A': 'value_counts', 'Survey_B': 'value_counts'})

但是NaN值将在输出数据框中:

>>> df
   x x2 x3
0  A  z  a
1  A  z  a
2  A  y  d
3  B  y  a
4  B  z  d

>>> df.groupby('x').agg({'x2': 'value_counts', 'x3': 'value_counts'})
      x2   x3
A a  NaN  2.0
  d  NaN  1.0
  y  1.0  NaN
  z  2.0  NaN
B a  NaN  1.0
  d  NaN  1.0
  y  1.0  NaN
  z  1.0  NaN

答案 1 :(得分:0)

我想您可以groupby并获得value_counts并对其进行规范化,但是我看不出它的运行速度快于您的功能:

df.groupby('Name').agg({i:'value_counts' for i in df.columns[1:]}).groupby(level=0).transform(lambda x: x.div(x.sum()))

        Survey_A    Survey_B
A   y   0.666667    0.333333
    z   0.333333    0.666667
B   y   0.333333    0.666667
    z   0.666667    0.333333