【问题标题】:Pandas fillna() based on specific column attribute基于特定列属性的 Pandas fillna()
【发布时间】:2017-01-07 15:09:04
【问题描述】:

假设我有这张桌子

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

Killed 上的某个值对于 [Type] = Dog 缺失。

我想将[Killed] 中的平均值估算为[Type] = Dog

我的代码如下:

  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] 的平均值。

【问题讨论】:

  • 你如何得到2.25的平均值?
  • @shivsn 我也想不通。
  • 我假设这只是一个错字或 OP 给出的平均值来自与问题中给出的数据不同的自己的数据。
  • @piRSquared 当我尝试时我很困惑然后发现他也在考虑 nan 值8/3
  • @shivsn 我认为可能也是这种情况。那么,你猜 OP 是指 2.66 ~= 2.25 吗?

标签: python pandas indexing nan mean


【解决方案1】:

groupbytransform

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

如果您打算在计算平均值时考虑np.nan

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

【讨论】:

  • 哇,我从来没有听说过transform... egads!它没有记录在案!?这是什么madness
【解决方案2】:

对我来说工作:

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

如果需要fillna by Series - 因为有 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

【讨论】:

  • 很高兴能为您提供帮助。美好的一天!
【解决方案3】:

两个问题:请注意,df.loc[(df['Type'] == 'Dog') & (df['Killed'])] 没有做(我认为)你认为它正在做的事情。不是选择类型为 dog 的行和列“Killed”,而是选择类型为 dog 的行,然后对列“Killed”进行元素“和”,这会给你带来垃圾 - False 正是列的位置杀死'是nan

见:

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。

【讨论】:

    猜你喜欢
    • 2019-10-02
    • 1970-01-01
    • 2022-10-24
    • 2020-11-22
    • 2021-01-10
    • 1970-01-01
    • 2013-06-24
    • 1970-01-01
    • 2015-04-04
    相关资源
    最近更新 更多