在 Pandas DataFrame 的多列上使用 fillna 方法失败
Using fillna method on multiple columns of a Pandas DataFrame failed
为什么这个操作会失败?
例如:
a = pd.DataFrame({'a': [1,2,np.nan, np.nan],
'b': [5,np.nan,6, np.nan],
'c': [5, 1, 5, 2]})
a[['a', 'b']].fillna(0, inplace=True)
并给了我这个警告:
SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
但是 a
仍然像以前一样充满了 NA
。但是,如果我分别在每一列上调用 .fillna()
,就不会有问题。如何一次性在多列中填充 NA
值?
这些答案的依据是 OP 希望对现有数据框进行就地编辑。通常,我会用一个新数据框覆盖现有数据框。
使用 pandas.DataFrame.fillna
和 dict
Pandas fillna
允许我们传递一个字典,指定将填充哪些列以及填充什么。
所以这会起作用
a.fillna({'a': 0, 'b': 0})
a b c
0 1.0 5.0 5
1 2.0 0.0 1
2 0.0 6.0 5
3 0.0 0.0 2
通过以下方式实现就地编辑:
a.fillna({'a': 0, 'b': 0}, inplace=True)
注意:我本来会这样做的 a = a.fillna({'a': 0, 'b': 0})
我们不保存文本长度,但我们可以使用 dict.fromkeys
变得可爱
a.fillna(dict.fromkeys(['a', 'b'], 0), inplace=True)
loc
我们可以使用与 OP 相同的格式,但使用 loc
将其放在正确的列中
a.loc[:, ['a', 'b']] = a[['a', 'b']].fillna(0)
a
a b c
0 1.0 5.0 5
1 2.0 0.0 1
2 0.0 6.0 5
3 0.0 0.0 2
pandas.DataFrame.update
明确地使用另一个数据框的非空值进行就地编辑
a.update(a[['a', 'b']].fillna(0))
a
a b c
0 1.0 5.0 5
1 2.0 0.0 1
2 0.0 6.0 5
3 0.0 0.0 2
逐列迭代
我真的不喜欢这种方法,因为它不必要地冗长
for col in ['a', 'b']:
a[col].fillna(0, inplace=True)
a
a b c
0 1.0 5.0 5
1 2.0 0.0 1
2 0.0 6.0 5
3 0.0 0.0 2
fillna
带有数据帧
使用 a[['a', 'b']].fillna(0)
的结果作为另一个 fillna
的输入。在我看来,这是愚蠢的。只用第一个选项。
a.fillna(a[['a', 'b']].fillna(0), inplace=True)
a
a b c
0 1.0 5.0 5
1 2.0 0.0 1
2 0.0 6.0 5
3 0.0 0.0 2
编辑:正如@piRSquared 指出的那样,第一个解决方案应该是
a.loc[:, ['a', 'b']] = a[['a', 'b']].fillna(0)
在选定的列中填写
或
a.fillna(0, inplace = True)
填写所有栏目
为什么这个操作会失败? 例如:
a = pd.DataFrame({'a': [1,2,np.nan, np.nan],
'b': [5,np.nan,6, np.nan],
'c': [5, 1, 5, 2]})
a[['a', 'b']].fillna(0, inplace=True)
并给了我这个警告:
SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
但是 a
仍然像以前一样充满了 NA
。但是,如果我分别在每一列上调用 .fillna()
,就不会有问题。如何一次性在多列中填充 NA
值?
这些答案的依据是 OP 希望对现有数据框进行就地编辑。通常,我会用一个新数据框覆盖现有数据框。
使用 pandas.DataFrame.fillna
和 dict
Pandas fillna
允许我们传递一个字典,指定将填充哪些列以及填充什么。
所以这会起作用
a.fillna({'a': 0, 'b': 0})
a b c
0 1.0 5.0 5
1 2.0 0.0 1
2 0.0 6.0 5
3 0.0 0.0 2
通过以下方式实现就地编辑:
a.fillna({'a': 0, 'b': 0}, inplace=True)
注意:我本来会这样做的 a = a.fillna({'a': 0, 'b': 0})
我们不保存文本长度,但我们可以使用 dict.fromkeys
a.fillna(dict.fromkeys(['a', 'b'], 0), inplace=True)
loc
我们可以使用与 OP 相同的格式,但使用 loc
a.loc[:, ['a', 'b']] = a[['a', 'b']].fillna(0)
a
a b c
0 1.0 5.0 5
1 2.0 0.0 1
2 0.0 6.0 5
3 0.0 0.0 2
pandas.DataFrame.update
明确地使用另一个数据框的非空值进行就地编辑
a.update(a[['a', 'b']].fillna(0))
a
a b c
0 1.0 5.0 5
1 2.0 0.0 1
2 0.0 6.0 5
3 0.0 0.0 2
逐列迭代
我真的不喜欢这种方法,因为它不必要地冗长
for col in ['a', 'b']:
a[col].fillna(0, inplace=True)
a
a b c
0 1.0 5.0 5
1 2.0 0.0 1
2 0.0 6.0 5
3 0.0 0.0 2
fillna
带有数据帧
使用 a[['a', 'b']].fillna(0)
的结果作为另一个 fillna
的输入。在我看来,这是愚蠢的。只用第一个选项。
a.fillna(a[['a', 'b']].fillna(0), inplace=True)
a
a b c
0 1.0 5.0 5
1 2.0 0.0 1
2 0.0 6.0 5
3 0.0 0.0 2
编辑:正如@piRSquared 指出的那样,第一个解决方案应该是
a.loc[:, ['a', 'b']] = a[['a', 'b']].fillna(0)
在选定的列中填写
或
a.fillna(0, inplace = True)
填写所有栏目