按组标准化数据帧系列

时间:2021-02-23 11:55:02

标签: python pandas dataframe

在这样的数据框中

id    name    month    count
111   a       1        5
112   b       1        4
113   c       1        6
111   a       2        1
112   b       2        7
113   c       2        6

我想分别标准化 a、b 和 c 的值。

最好的方法可能是分组和聚合,如下所示:

df_normalized = df.groupby(["id", "name"]).agg(normalized_count=("count", "lambda x: (x - x.mean()) / x.std())")).reset_index(drop=True)

然而,这会导致 AttributeError。

AttributeError: 'SeriesGroupBy' object has no attribute 'lambda x: (x - x.mean()) / x.std())'

这是使用转换的类似方法,不幸的是它似乎不尊重“a,b,c”。

Normalize DataFrame by group

另一种方式,在同一个线程中,相当丑陋,并且使用多个步骤:

means_stds = df.groupby('indx')['a0'].agg(['mean','std']).reset_index()
df = df.merge(means_stds,on='indx')
df['a0_normalized'] = (df['a0'] - df['mean']) / df['std']

有没有办法使用 groupby 来实现这一点?

1 个答案:

答案 0 :(得分:3)

在 lambda 函数中使用 GroupBy.transform

df['c1_normalized'] = (df.groupby(["id", "name"])['count']
                         .transform(lambda x: (x - x.mean()) / x.std()))

为了比较改变你的第二个解决方案:

means_stds = df.groupby(["id", "name"])['count'].agg(['mean','std']).reset_index()
df = df.merge(means_stds,on=["id", "name"])
df['c2_normalized'] = (df['count'] - df['mean']) / df['std']
print (df)
    id name  month  count  c1_normalized  mean       std  c2_normalized
0  111    a      1      5       0.707107   3.0  2.828427       0.707107
1  111    a      2      1      -0.707107   3.0  2.828427      -0.707107
2  112    b      1      4      -0.707107   5.5  2.121320      -0.707107
3  112    b      2      7       0.707107   5.5  2.121320       0.707107
4  113    c      1      6            NaN   6.0  0.000000            NaN
5  113    c      2      6            NaN   6.0  0.000000            NaN