在 Pandas 中按组均值创建大均值中心变量
Posted
技术标签:
【中文标题】在 Pandas 中按组均值创建大均值中心变量【英文标题】:Create Grand Mean Centered Variables by Group Means in Pandas 【发布时间】:2021-07-08 16:43:00 【问题描述】:我正在尝试按组创建以均值为中心的大变量。
样本数据为:
import pandas as pd
import numpy as np
dat =
'group': ['1', '1', '1', '2', '2', '1', '2'],
'age': [40, 29, 34, 35, 37, 32, 36],
'weight': [150, 175, 135, 125, 189, 178, 137],
'score': [98.0, 77.0, 88.0, 78.0, 78.0, 85.0, 84.0]
df = pd.DataFrame(data=dat)
我正在尝试编写一个函数,该函数将按组估计数据集中所有变量的总均值中心变量。我要尝试的代码如下:
def group_mean_centered(x):
d = []
d.append(x.groupby(x.iloc[:, 0]).transform('mean') - x.iloc[:,0:].mean())
d = np.asarray(d)
d_ = d.reshape(-1,len(x.columns))
dd = pd.DataFrame(d_, columns=[list(x.columns.values)])
return dd
但是,当我这样做时,它会返回一个数据框,其中分组变量 group 也被转换,而不是像括号 [] 中那样获取组
group age weight score
0 -0.428571 [1] -0.964286 3.928571 3.0
1 -0.428571 [1] -0.964286 3.928571 3.0
2 -0.428571 [1] -0.964286 3.928571 3.0
3 0.571429 [2] 1.285714 -5.238095 -4.0
4 0.571429 [2] 1.285714 -5.238095 -4.0
5 -0.428571 [1] -0.964286 3.928571 3.0
6 0.571429 [2] 1.285714 -5.238095 -4.0
只是寻找一些关于如何修复代码以保持分组变量 group 不变而不是转换它的想法。
【问题讨论】:
【参考方案1】:我们可以用groupby
+ transform
来计算group
的平均值,然后减去mean
的大mean
仅列
df[['group']].join(df.groupby('group').transform('mean') - df.mean(numeric_only=True))
或者我们可以将数据帧的索引设置为group
,然后在level=0
上设置groupby
和transform
来计算组均值,然后从梯度中减去这个转换后的组均值意思是得到结果。
s = df.set_index('group')
s.groupby(level=0).transform('mean').sub(s.mean()).reset_index()
group age weight score
0 1 -0.964286 3.928571 3.0
1 1 -0.964286 3.928571 3.0
2 1 -0.964286 3.928571 3.0
3 2 1.285714 -5.238095 -4.0
4 2 1.285714 -5.238095 -4.0
5 1 -0.964286 3.928571 3.0
6 2 1.285714 -5.238095 -4.0
【讨论】:
【参考方案2】:如果您对其他解决方案没问题,您所做的也可以直接由groupby.transform
完成。
out = ((df.groupby("group").transform("mean")-df.mean())
.fillna("group":df['group']).reindex(columns=df.columns))
print(out)
group age weight score
0 1 -0.964286 3.928571 3.0
1 1 -0.964286 3.928571 3.0
2 1 -0.964286 3.928571 3.0
3 2 1.285714 -5.238095 -4.0
4 2 1.285714 -5.238095 -4.0
5 1 -0.964286 3.928571 3.0
6 2 1.285714 -5.238095 -4.0
【讨论】:
【参考方案3】:我在您的函数中添加了以下行:dd.iloc[:,0]=x.iloc[:,0]
。所以完整的功能是:
def group_mean_centered(x):
d = []
d.append(x.groupby(x.iloc[:, 0]).transform('mean') - x.iloc[:,0:].mean())
d = np.asarray(d)
d_ = d.reshape(-1,len(x.columns))
dd = pd.DataFrame(d_, columns=[list(x.columns.values)])
dd.iloc[:,0]=x.iloc[:,0]
return dd
这个想法是用原始列替换组列。
返回:
group age weight score
0 1 -0.964286 3.928571 3.0
1 1 -0.964286 3.928571 3.0
2 1 -0.964286 3.928571 3.0
3 2 1.285714 -5.238095 -4.0
4 2 1.285714 -5.238095 -4.0
5 1 -0.964286 3.928571 3.0
6 2 1.285714 -5.238095 -4.0
根据需要。
其他想法:
我像你一样使用了.iloc
方法,尽管我可能会考虑为你的函数添加一个 groupby 列名的变量,这样你就可以获得更大的灵活性,并且可以利用 pandas 在可读性方面优于 numpy 的优势/便于使用。您始终可以将默认值设置为“组”,这样您就不必在此应用程序中考虑它,但可以在另一个数据帧上使用相同的函数(其中第一列不是分组变量)。
【讨论】:
以上是关于在 Pandas 中按组均值创建大均值中心变量的主要内容,如果未能解决你的问题,请参考以下文章