基于条件切片的Pandas数据帧中单元的改变

2021-04-11 15:06:07 发布

您现在位置:Python中文网/ 问答频道 /正文

我在玩Titanic数据集,我想做的是用基于Pclass的中值填充Age列的所有NaN/Null值。在

以下是一些数据:

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

最后我想说的是:

^{pr2}$

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

Pclass_1 = train['Pclass']==1

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

据我所知,这种方法创建一个视图,而不是编辑train本身(我不太明白这与副本有什么不同,或者它们在内存方面是否相似——如果可能的话,这是我很乐意听到的旁白)。我特别喜欢这个关于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]返回异常IndexingError: Unalignable boolean Series key provided。在

1条回答
网友
1楼 ·

在这段线路上

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

部件['Pclass'] == 1将列表['Pclass']与返回False的值1进行比较。然后,.loc[]被计算为导致错误的.loc[:,False]。在

我想你的意思是:

^{pr2}$

它选择Pclass为1的所有行。这修复了错误,但仍将提供“SettingWithCopyWarning”。在

编辑1

(删除旧代码)

这里有一个方法,它使用groupbytransform来创建Series 包含每个Pclass的中值Age。然后使用Series作为fillna()的参数,用中值替换丢失的值。使用这种方法将同时纠正所有乘客等级,这正是OP最初要求的。答案来自于Python-pandas Replace NA with the median or mean of a group in dataframe

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)

相关问题