我有一个样本数据框,通常如下所示:
df = pd.Dataframe({'Class': [1, 2, 3, 2, 1, 2, 3, 2],
'Sex': [1, 0, 0, 0, 1, 1, 0, 1],
'Age': [15, 24, 13, 28, 29, NaN, 34, 27]})
显示为:
Age Class Sex
0 15.0 1 1
1 24.0 2 0
2 13.0 2 0
3 28.0 2 0
4 29.0 1 1
5 NaN 2 1
6 34.0 1 0
7 27.0 2 1
我想要做的是在'Age'系列中填写每个NaN值,其中包含所有具有'Class'和'Sex'分组的条目的中值。
例如,当我像这样访问这些值时:
df.groupby(['Class', 'Sex'])['Age'].median()
并获得:
Class Sex
1 0 34.0
1 22.0
2 0 24.0
1 27.0
我想编写一个自动填充现有NaN值27的函数,因为那是Class值为2且Sex值为1的条目的中位数。
现在我有:
df['Age'] = df.groupby(['Class', 'Sex'])['Age'].apply(lambda x: x.median() if pd.isnull(x) else x)
我收到以下错误:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
然而,在this question和this one的答案中使用了非常相似的语法,所以我不太清楚为什么我的不起作用,特别是后者也使用isnull方法在它的lambda函数中,所以我不清楚为什么我的工作不起作用,但是那个人没有。
我也尝试过使用fillna方法:
df['Age'] = df['Age'].fillna(df.groupby(['Class', 'Sex'])['Age'].median())
但收到以下错误消息:
ValueError: Buffer dtype mismatch, expected 'Python object' but got 'long long'
我对其他获得相同值的方法持开放态度,但更喜欢完全依赖Pandas方法的东西,而不必使用单独的for循环并将其传递给'Apply'方法,以使其尽可能简洁
谢谢。
答案 0 :(得分:2)
一种选择是使用transform
将空值替换为Age
列的中位数:
df['Age'] = df.groupby(['Class', 'Sex']).Age.transform(lambda col: col.where(col.notnull(), col.median()))
df
# Age Class Sex
#0 15.0 1 1
#1 24.0 2 0
#2 13.0 3 0
#3 28.0 2 0
#4 29.0 1 1
#5 27.0 2 1
#6 34.0 3 0
#7 27.0 2 1
或者使用replace
方法代替where
也可以:
df['Age'] = df.groupby(['Class', 'Sex']).Age.transform(lambda col: col.replace(np.nan, col.median()))