在这样的数据框中
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”。
另一种方式,在同一个线程中,相当丑陋,并且使用多个步骤:
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 来实现这一点?
答案 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