用groupby均值替换值

14 投票
4 回答
24314 浏览
提问于 2025-04-17 15:09

我有一个数据表,其中有一列数据包含了一些不好的数据,比如一些负值。我想把这些小于0的值替换成它们所在组的平均值。

对于缺失值(也就是NAs),我会这样做:

data = df.groupby(['GroupID']).column
data.transform(lambda x: x.fillna(x.mean()))

但是,像这样处理小于0的条件 x < 0,该怎么做呢?

谢谢!

4 个回答

2

我也遇到过同样的问题,找到了一种比较简单的解决办法。

func = lambda x : np.where(x < 0, x.mean(), x)

df['Bad_Column'].transform(func)

注意,如果你想要返回正确值的平均数(也就是只计算正值的平均数),你需要特别说明一下:

func = lambda x : np.where(x < 0, x.mask(x < 0).mean(), x)
3

这里有一种方法可以做到这一点(以这个无聊的例子中的 'b' 列为例):

In [1]: df = pd.DataFrame([[1,1],[1,-1],[2,1],[2,2]], columns=list('ab'))
In [2]: df
Out[2]: 
   a  b
0  1  1
1  1 -1
2  2  1
3  2  2

先把那些负值替换成 NaN(表示缺失值),然后在每个组里计算平均值(b):

In [3]: df['b'] = df.b.apply(lambda x: x if x>=0 else pd.np.nan)
In [4]: m = df.groupby('a').mean().b

接着,使用 apply 方法,逐行处理,把每个 NaN 替换成它所在组的平均值:

In [5]: df['b'] = df.apply(lambda row: m[row['a']]
                                       if pd.isnull(row['b'])
                                       else row['b'],
                           axis=1) 
In [6]: df
Out[6]: 
   a  b
0  1  1
1  1  1
2  2  1
3  2  2
13

根据@AndyHayden的例子,你可以使用 groupbytransform 结合 replace 来实现:

df = pd.DataFrame([[1,1],[1,-1],[2,1],[2,2]], columns=list('ab'))
print(df)
#    a  b
# 0  1  1
# 1  1 -1
# 2  2  1
# 3  2  2

data = df.groupby(['a'])
def replace(group):
    mask = group<0
    # Select those values where it is < 0, and replace
    # them with the mean of the values which are not < 0.
    group[mask] = group[~mask].mean()
    return group
print(data.transform(replace))
#    b
# 0  1
# 1  1
# 2  1
# 3  2

撰写回答