根据条件切片更改 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
(旧代码已删除)
这是一种使用 groupby
和 transform
来创建 Series
的方法
包含每个 Pclass
的中位数 Age
。 Series
然后用作 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)
我正在玩泰坦尼克号数据集,我想做的是用基于 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
(旧代码已删除)
这是一种使用 groupby
和 transform
来创建 Series
的方法
包含每个 Pclass
的中位数 Age
。 Series
然后用作 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)