是否有任何方法可以用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安装了pandas Superpack脚本,供您参考。
答案 0 :(得分:83)
实际上在更高版本的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
答案 1 :(得分:14)
where
可能是你正在寻找的东西。所以
data=data.where(data=='-', None)
来自panda docs:
where
[返回]一个与self相同形状的对象,其对应的条目来自self,其中cond为True,否则来自其他)。
答案 2 :(得分:11)
我更喜欢使用replace
和dict
的解决方案,因为它简单而优雅:
df.replace({'-': None})
您还可以拥有更多替代品:
df.replace({'-': None, 'None': None})
即使对于更大的替代品,在我看来,总是显而易见并清楚什么被什么取代 - 这对于长列表来说更难。
答案 3 :(得分:2)
df = pd.DataFrame(['-',3,2,5,1,-5,-1,'-',9])
df = df.where(df!='-', None)
答案 4 :(得分:2)
在继续此文章之前,务必要了解 the difference between NaN and None。 一种是浮点类型,另一种是对象类型。熊猫更好 适合使用标量类型,因为这些类型上的许多方法都可以 被向量化。熊猫确实尝试一致地处理None和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,请执行
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
与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中找到。
答案 5 :(得分:0)
可以使用np.nan
设置空值:
import numpy as np
df.replace('-', np.nan)
优点是df.last_valid_index()
将其识别为无效。
答案 6 :(得分:0)
使用替换并分配新的df:
import pandas as pd
df = pd.DataFrame(['-',3,2,5,1,-5,-1,'-',9])
dfnew = df.replace('-', 0)
print(dfnew)
(venv) D:\assets>py teste2.py
0
0 0
1 3
2 2
3 5
4 1
5 -5
答案 7 :(得分:0)
df.replace('-', np.nan).astype("object")
这将确保您稍后可以在数据框中使用isnull()
答案 8 :(得分:0)
对于Pandas版本≥1.0.0,我将使用DataFrame.replace
或Series.replace
:
df.replace(old_val, pd.NA, inplace=True)
这有两个更好的理由:
pd.NA
而不是None
或np.nan
。