基于特定列属性的 Pandas fillna() 方法

4

假设我有这个表格

Type | Killed | Survived
Dog      5         2
Dog      3         4
Cat      1         7
Dog     nan        3
cow     nan        2

[Type] = Dog中,Killed的一个值缺失。

我想要在[Type] = Dog中用[Killed]的平均数来填充缺失值。

我的代码如下:

  1. 搜索平均数

df[df['Type'] == 'Dog'].mean().round()

这将给出平均值(约为2.25)

  1. 填充平均数(这是问题开始的地方)

df.loc[(df['Type'] == 'Dog') & (df['Killed'])].fillna(2.25, inplace = True)

代码运行了,但值没有被填充,NaN值仍然存在。

我的问题是,如何根据[Type] = Dog[Killed]中填充平均数。


1
你如何得到平均值为 2.25 - shivsn
@shivsn 我也想不出来。 - piRSquared
我认为这只是一个笔误,或者OP给出的平均值来自于与问题中给出的数据不同的数据。 - juanpa.arrivillaga
@piRSquared 当我尝试时感到困惑,然后弄清楚他也考虑了nan值 8/3 - shivsn
@shivsn 我也认为可能是这种情况。那么,你猜测 OP 的意思是 2.66 ~= 2.25 吗? - piRSquared
@piRSquared 是的,没错。 - shivsn
3个回答

3

对我来说工作:

df.ix[df['Type'] == 'Dog', 'Killed'] = df.ix[df['Type'] == 'Dog', 'Killed'].fillna(2.25)
print (df)
  Type  Killed  Survived
0  Dog    5.00         2
1  Dog    3.00         4
2  Cat    1.00         7
3  Dog    2.25         3
4  cow     NaN         2

如果需要通过Series进行fillna - 因为有2列KilledSurvived
m = df[df['Type'] == 'Dog'].mean().round()
print (m)
Killed      4.0
Survived    3.0
dtype: float64

df.ix[df['Type'] == 'Dog'] = df.ix[df['Type'] == 'Dog'].fillna(m)
print (df)
  Type  Killed  Survived
0  Dog     5.0         2
1  Dog     3.0         4
2  Cat     1.0         7
3  Dog     4.0         3
4  cow     NaN         2

如果只需要在列Killed中填充缺失值:
#if dont need rounding, omit it
m = round(df.ix[df['Type'] == 'Dog', 'Killed'].mean())
print (m)
4

df.ix[df['Type'] == 'Dog', 'Killed'] = df.ix[df['Type'] == 'Dog', 'Killed'].fillna(m)
print (df)
  Type  Killed  Survived
0  Dog     5.0         2
1  Dog     3.0         8
2  Cat     1.0         7
3  Dog     4.0         3
4  cow     NaN         2

您可以重复使用类似以下的代码:

filtered = df.ix[df['Type'] == 'Dog', 'Killed']
print (filtered)
0    5.0
1    3.0
3    NaN
Name: Killed, dtype: float64

df.ix[df['Type'] == 'Dog', 'Killed'] = filtered.fillna(filtered.mean())
print (df)
  Type  Killed  Survived
0  Dog     5.0         2
1  Dog     3.0         8
2  Cat     1.0         7
3  Dog     4.0         3
4  cow     NaN         2

很高兴能帮助你。祝你有美好的一天! - jezrael

3

groupby 结合 transform 使用

df.groupby('Type').Killed.transform(lambda x: x.fillna(x.mean()))

设置

df = pd.DataFrame([
        ['Dog', 5, 2],
        ['Dog', 3, 4],
        ['Cat', 1, 7],
        ['Dog', np.nan, 3],
        ['Cow', np.nan, 2]
    ], columns=['Type', 'Killed', 'Survived'])

df.Killed = df.groupby('Type').Killed.transform(lambda x: x.fillna(x.mean()))
df

enter image description here

如果你在计算平均值时想要考虑 np.nan

df.Killed = df.groupby('Type').Killed.transform(lambda x: x.fillna(x.fillna(0).mean()))
df

enter image description here


哇,我从未听说过transform...天哪!它没有文档说明吗?这是什么疯狂啊? - juanpa.arrivillaga

1
两个问题:请注意,df.loc[(df['Type'] == 'Dog') & (df['Killed'])]并不是做你想象中的事情。它选择的不是类型为狗且有‘Killed’列的行,而是选择了类型为狗的行,然后与‘Killed’列逐元素进行“and”运算,这会给你垃圾数据-在列‘Killed’为nan的位置上恰好为False!请看:
In [6]: df.loc[(df['Type'] == 'Dog') & (df['Killed'])]
Out[6]: 
  Type  Killed  Survived
0  Dog     5.0         2
1  Dog     3.0         4

你想要的是以下内容:
In [5]: df.loc[(df['Type'] == 'Dog'), ['Killed']]
Out[5]: 
   Killed
0     5.0
1     3.0
3     NaN

另一个问题是你需要将赋值与 .loc.fillna 结合使用,像下面这样:

In [6]: df.loc[(df['Type'] == 'Dog'), ['Killed']] = df.loc[(df['Type'] == 'Dog'), ['Killed']].fillna(2.25)

In [7]: df
Out[7]: 
  Type  Killed  Survived
0  Dog    5.00         2
1  Dog    3.00         4
2  Cat    1.00         7
3  Dog    2.25         3
4  cow     NaN         2

注意

您提供的平均值是错误的或与您在答案中提供的数据不符。平均值应为4。


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