101

有什么方法可以用NonePython 中的 Pandas 替换值吗?

您可以使用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,然后再转换NaNNone,但我想知道为什么数据框的行为如此糟糕。

在 Python 2.7 和 OS X 10.8 上的 pandas 0.12.0 dev 上测试。Python 是 OS X 上的预安装版本,我使用 SciPy Superpack 脚本安装了 pandas,供您参考。

4

9 回答 9

125

实际上,在更高版本的 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
于 2013-06-13T21:29:01.457 回答
29

我更喜欢使用replacewith a的解决方案,dict因为它简单而优雅:

df.replace({'-': None})

你也可以有更多的替代品:

df.replace({'-': None, 'None': None})

即使对于更大的替换,什么被什么替换总是很明显和清楚的——在我看来,这对于长列表来说更难。

于 2018-03-21T12:31:05.530 回答
17

where可能是您正在寻找的。所以

data=data.where(data=='-', None) 

来自熊猫文档

where[返回] 一个与 self 形状相同的对象,其对应条目来自 self ,其中 cond 为 True ,否则来自 other )。

于 2014-04-09T21:38:12.773 回答
11

在继续这篇文章之前,了解NaN 和 None 之间的区别很重要。一个是浮点类型,另一个是对象类型。Pandas 更适合使用标量类型,因为这些类型的许多方法都可以向量化。Pandas 确实尝试一致地处理 None 和 NaN,但 NumPy 不能。

我的建议(和安迪的)是坚持使用 NaN。

但是要回答你的问题...

pandas >= 0.18:使用na_values=['-']参数read_csv

如果您从 CSV/Excel 加载此数据,我有好消息要告诉您。您可以在数据加载期间从根部取消此操作,而不必在后续步骤中使用代码编写修复程序。

大多数pd.read_*函数(例如read_csvread_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

其他功能/文件格式也类似。

PS:在 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 的整数类型。还有其他选择。


处理数值数据:pd.to_numericwitherrors='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

...并在之后分配结果。

更多信息可以在这个答案中找到。

于 2019-04-02T07:43:16.600 回答
5

对于 Pandas 版本≥1.0.0,我会使用DataFrame.replaceor Series.replace

df.replace(old_val, pd.NA, inplace=True)

这更好有两个原因:

  1. 它使用pd.NA代替Noneor np.nan
  2. 它可以选择就地工作,这可以根据内部实现提高内存效率。
于 2020-10-14T21:57:42.860 回答
3
df = pd.DataFrame(['-',3,2,5,1,-5,-1,'-',9])
df = df.where(df!='-', None)
于 2019-01-13T02:21:08.520 回答
0

可以通过以下方式设置空值np.nan

import numpy as np
df.replace('-', np.nan)

优点是df.last_valid_index()承认这些是无效的。

于 2019-03-15T08:15:46.580 回答
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
于 2019-12-28T12:30:12.327 回答
0
df.replace('-', np.nan).astype("object")

这将确保您isnull()以后可以在数据框上使用

于 2020-05-21T16:05:23.140 回答