添加一个新的pandas dataframe列,使用条件计算填充它(如果是平均值,则为平均值;如果是标准差,则为标准差)。

3
我需要向一个Pandas数据框中添加2列,这两列包含有条件的平均值和标准差。
# Import pandas library 
import pandas as pd 

# Initialize list of lists 
data = [
    ['Tom',   'Blue', 'Small',  10, ], 
    ['Tom',   'Blue', 'Big',    15, ], 
    ['Tom',   'Red',  'Big',     3, ], 
    ['Tom',   'Red',  'Small',   8, ], 
    ['Tom',   'Red',  'Medium',  5, ], 
    ['Tom',   'Blue', 'Medium', 12, ], 
    ['Nick',  'Blue', 'Small',  15, ], 
    ['Nick',  'Red',  'Medium', 11, ], 
    ['Nick',  'Red',  'Small',  17, ], 
    ['Julie', 'Blue', 'Big',    14, ], 
    ['Julie', 'Red',  'Big',    11, ],
    ['Julie', 'Red',  'Medium',  3, ], 
    ['Julie', 'Red',  'Medium',  4, ],
]

# Create the pandas DataFrame 
df = pd.DataFrame(data, columns = ['Name', 'Colour', 'Size', 'Age']) 

# print dataframe. 
df

在这个示例中,我需要添加两列:df['mean']df['std'],仅限于名称和颜色的条件。
我查看了.mean().std()文档,但没有找到添加一组条件的方法。我认为我可能需要两个函数,对于每一行,将名称和颜色作为参数,计算整个系列的平均值或标准差,然后填充新的列。

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.std.html

我认为我需要一个函数,动态检查每一行的名称和颜色,因为我的应用程序是针对有数千个名称和数千种颜色的数据框架,不像这个示例数据框架。
我知道如何将.mean或.std应用于整个pandas系列,而不需要条件:
df['Age'].std()

或者

df['Age'].mean()

我还发现,使用分组和转换操作可以做一些类似的事情,但没有函数能够动态检查每一行。
df['mean'] = df.groupby(['Name','Colour']).transform('mean')

感谢你的帮助。
这是我期望的输出结果。感谢解答: 输出数据帧

2
在给定的输入下,您能提供您期望的输出吗? - G. Anderson
2
df.groupby(['Name', 'Colour']).transform('mean')有什么问题? - Dan
下面的解决方案对于平均值来说是可以的:df.groupby(['Name','Colour']).transform('mean')但我没有找到标准差的等效方法。df.groupby(['Name','Colour']).transform('std') <- 这个不起作用。 - Alphynn
你能否添加你期望的输出,这样我们就可以停止猜测游戏了。谢谢。 - Erfan
@Alphynn 使用 stdtransform 应该可以工作。你能否评论一下为什么不行?我猜测你会得到 ValueError: Wrong number of items passed 2, placement implies 1 是因为你需要仅转换 Age 列。在添加了 mean 列之后,它也会进行转换。 - ALollz
@ALollz 猜得真好!你说得对,这就是我遇到的错误。谢谢! - Alphynn
1个回答

3

由于transform不支持std,我们可以通过groupby().aggmerge进行绕过:

new_df = df.groupby(['Name', 'Colour']).Age.agg({'mean','std'})
df = df.merge(new_df, left_on=['Name', 'Colour'], right_index=True)

输出:

     Name Colour    Size  Age       std       mean
0     Tom   Blue   Small   10  2.516611  12.333333
1     Tom   Blue     Big   15  2.516611  12.333333
5     Tom   Blue  Medium   12  2.516611  12.333333
2     Tom    Red     Big    3  2.516611   5.333333
3     Tom    Red   Small    8  2.516611   5.333333
4     Tom    Red  Medium    5  2.516611   5.333333
6    Nick   Blue   Small   15       NaN  15.000000
7    Nick    Red  Medium   11  4.242641  14.000000
8    Nick    Red   Small   17  4.242641  14.000000
9   Julie   Blue     Big   14       NaN  14.000000
10  Julie    Red     Big   11  4.358899   6.000000
11  Julie    Red  Medium    3  4.358899   6.000000
12  Julie    Red  Medium    4  4.358899   6.000000

2
我错过了什么吗?df.groupby(['Name','Colour']).Age.transform('std')可以工作。 - ALollz
1
这是来自原帖作者的评论。也许可以使用 df.groupby(['Name', 'Colour']).Age.transform('std') - Quang Hoang
啊!确实是这样。对于均值计算,不需要使用.Age.,但对于标准差,必须使用.Age.。为了代码一致性,我已经将.Age添加到两个语句中,并且它可以正常工作: df['mean'] = df.groupby(['Name','Colour']).Age.transform('mean') df['std']=df.groupby(['Name','Colour']).Age.transform('std')谢谢! - Alphynn
感谢您提供的解决方案,虽然看起来有些复杂(但也许是必要的——我并不是说您的解决方案不好)。 - Antonio Sesto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接