根据条件切片更改 Pandas DataFrame 中的单元格

Change Cells in Pandas DataFrame Based on Conditional Slices

我正在玩泰坦尼克号数据集,我想做的是用基于 Age 列的中值填充所有 NaN/Null 值 Pclass

这是一些数据:

train

PassengerId Pclass  Age
0   1   3   22
1   2   1   35
2   3   3   26
3   4   1   35
4   5   3   35
5   6   1   NaN
6   7   1   54
7   8   3   2
8   9   3   27
9   10  2   14
10  11  1   Nan

这里是我想要结束的:

PassengerId Pclass  Age
0   1   3   22
1   2   1   35
2   3   3   26
3   4   1   35
4   5   3   35
5   6   1   35
6   7   1   54
7   8   3   2
8   9   3   27
9   10  2   14
10  11  1   35

我想到的第一件事是 - 为了简洁起见,我只包含一个 Pclass 等于 1 的切片,而不是包含 2 和 3:

Pclass_1 = train['Pclass']==1

train[Pclass_1]['Age'].fillna(train[train['Pclass']==1]['Age'].median(), inplace=True)

据我所知,此方法创建视图而不是编辑 train 本身(我不太明白这与副本有何不同,或者它们在内存方面是否类似 - - 这是一个旁白,如果可能的话,我很想听听)。我特别喜欢这个 Q/A 主题 View vs Copy, How Do I Tell?,但它不包含我正在寻找的见解。

通过 Pandas 文档我了解了为什么要使用 .loc 来避免这个陷阱。但是我似乎无法正确使用语法。

Pclass_1 = train.loc[:,['Pclass']==1]

Pclass_1.Age.fillna(train[train['Pclass']==1]['Age'].median(),inplace=True)

我迷失在索引中。这个最终会寻找一个名为 False 的列,这显然不存在。如果没有链式索引,我不知道该怎么做。 train.loc[:,train['Pclass']==1] returns 异常 IndexingError: Unalignable boolean Series key provided.

在这部分行中,

train.loc[:,['Pclass']==1]

['Pclass'] == 1 部分正在将列表 ['Pclass'] 与值 1 进行比较,后者 returns False。然后 .loc[] 被评估为 .loc[:,False] 导致错误。

我想你的意思是:

train.loc[train['Pclass']==1]

选择 Pclass 为 1 的所有行。这修复了错误,但它仍然会给你 "SettingWithCopyWarning"。

编辑 1

(旧代码已删除)

这是一种使用 groupbytransform 来创建 Series 的方法 包含每个 Pclass 的中位数 AgeSeries 然后用作 fillna() 的参数,用中位数替换缺失值。使用这种方法将同时纠正所有 passenger 类,这是 OP 最初要求的。解决方案来自

的答案
import pandas as pd
from io import StringIO

tbl = """PassengerId Pclass  Age
0   1   3   22
1   2   1   35
2   3   3   26
3   4   1   35
4   5   3   35
5   6   1
6   7   1   54
7   8   3   2
8   9   3   27
9   10  2   14
10  11  1
"""

train = pd.read_table(StringIO(tbl), sep='\s+')
print('Original:\n', train)
median_age = train.groupby('Pclass')['Age'].transform('median') #median Ages for all groups
train['Age'].fillna(median_age, inplace=True)
print('\nNaNs replaced with median:\n', train)

代码产生:

 Original:
     PassengerId  Pclass   Age
0             1       3  22.0
1             2       1  35.0
2             3       3  26.0
3             4       1  35.0
4             5       3  35.0
5             6       1   NaN
6             7       1  54.0
7             8       3   2.0
8             9       3  27.0
9            10       2  14.0
10           11       1   NaN

NaNs replaced with median:
     PassengerId  Pclass   Age
0             1       3  22.0
1             2       1  35.0
2             3       3  26.0
3             4       1  35.0
4             5       3  35.0
5             6       1  35.0
6             7       1  54.0
7             8       3   2.0
8             9       3  27.0
9            10       2  14.0
10           11       1  35.0

需要注意的是这一行,它使用了inplace=True:

train['Age'].fillna(median_age, inplace=True)

可以使用.loc替换为赋值:

train.loc[:,'Age'] = train['Age'].fillna(median_age)