是否有任何方法可以在Python中的Pandas中用None
替换值?
你可以使用df.replace('pre', 'post')
并且可以用另一个值替换一个值,但是如果你想用None
值替换它就无法做到,如果你尝试,你会得到一个奇怪的结果。
所以这是一个例子:
df = DataFrame(['-',3,2,5,1,-5,-1,'-',9])
df.replace('-', 0)
返回成功的结果。
但,
df.replace('-', None)
返回以下结果:
0
0 - // this isn't replaced
1 3
2 2
3 5
4 1
5 -5
6 -1
7 -1 // this is changed to `-1`...
8 9
为什么会返回这么奇怪的结果?
由于我想将这个数据帧倒入MySQL数据库,我不能将NaN
值放入我的数据框中的任何元素,而是想放置None
。当然,您可以先将'-'
更改为NaN
,然后将NaN
转换为None
,但我想知道为什么数据帧会以如此糟糕的方式运行。
在Python 2.7和OS X 10.8上测试了pandas 0.12.0 dev。 Python是OS X上的预安装版本,我使用SciPy Superpack脚本安装了pandas,供您参考。
实际上在更高版本的pandas中,这会产生一个TypeError:
df.replace('-', None)
TypeError: If "to_replace" and "value" are both None then regex must be a mapping
您可以通过传递列表或字典来完成:
In [11]: df.replace('-', df.replace(['-'], [None]) # or .replace('-', {0: None})
Out[11]:
0
0 None
1 3
2 2
3 5
4 1
5 -5
6 -1
7 None
8 9
但我建议使用NaN而不是None:
In [12]: df.replace('-', np.nan)
Out[12]:
0
0 NaN
1 3
2 2
3 5
4 1
5 -5
6 -1
7 NaN
8 9
where
可能就是你想要的。所以
data=data.where(data=='-', None)
来自panda docs:
where
[返回]一个与self相同形状的对象,其对应的条目来自self,其中cond为True,否则来自其他)。
我更喜欢使用replace
和dict
的解决方案,因为它简单而优雅:
df.replace({'-': None})
您还可以拥有更多替代品:
df.replace({'-': None, 'None': None})
即使对于更大的替代品,在我看来,总是显而易见并清楚什么被什么取代 - 这对于长列表来说更难。
在继续这篇文章之前,了解the difference between NaN and None非常重要。一个是浮点类型,另一个是对象类型。 Pandas更适合使用标量类型,因为这些类型的许多方法都可以进行矢量化。熊猫确实试图一致地处理无和NaN,但NumPy不能。
我的建议(and Andy's)是坚持使用NaN。
na_values=['-']
如果你从CSV / Excel加载这些数据,我有个好消息。您可以在数据加载期间在根目录中撤消此操作,而不必编写包含代码的修补程序作为后续步骤。
大多数pd.read_*
函数(例如read_csv
和read_excel
)接受na_values
属性。
file.csv
A,B
-,1
3,-
2,-
5,3
1,-2
-5,4
-1,-1
-,0
9,0
现在,要将-
字符转换为NaN,do,
import pandas as pd
df = pd.read_csv('file.csv', na_values=['-'])
df
A B
0 NaN 1.0
1 3.0 NaN
2 2.0 NaN
3 5.0 3.0
4 1.0 -2.0
5 -5.0 4.0
6 -1.0 -1.0
7 NaN 0.0
8 9.0 0.0
和其他功能/文件格式类似。
P.S。:在v0.24 +上,你可以保留整数类型,即使你的列有NaN(是的,谈论有蛋糕并且也吃它)。你可以指定dtype='Int32'
df = pd.read_csv('file.csv', na_values=['-'], dtype='Int32')
df
A B
0 NaN 1
1 3 NaN
2 2 NaN
3 5 3
4 1 -2
5 -5 4
6 -1 -1
7 NaN 0
8 9 0
df.dtypes
A Int32
B Int32
dtype: object
dtype不是传统的int类型......而是Nullable Integer Type.还有其他选择。
pd.to_numeric
with errors='coerce
如果您正在处理数值数据,更快的解决方案是使用pd.to_numeric
和errors='coerce'
参数,该参数将无效值(无法转换为数字的值)强制转换为NaN。
pd.to_numeric(df['A'], errors='coerce')
0 NaN
1 3.0
2 2.0
3 5.0
4 1.0
5 -5.0
6 -1.0
7 NaN
8 9.0
Name: A, dtype: float64
要保留(可为空)整数dtype,请使用
pd.to_numeric(df['A'], errors='coerce').astype('Int32')
0 NaN
1 3
2 2
3 5
4 1
5 -5
6 -1
7 NaN
8 9
Name: A, dtype: Int32
要强制使用多个列,请使用apply
:
df[['A', 'B']].apply(pd.to_numeric, errors='coerce').astype('Int32')
A B
0 NaN 1
1 3 NaN
2 2 NaN
3 5 3
4 1 -2
5 -5 4
6 -1 -1
7 NaN 0
8 9 0
...并在之后重新分配结果。
更多信息可以在this answer找到。
df = pd.DataFrame(['-',3,2,5,1,-5,-1,'-',9])
df = df.where(df!='-', None)
可以使用np.nan
设置空值:
import numpy as np
df.replace('-', np.nan)
优点是df.last_valid_index()
认为这些无效。