如何使用pandas将None替换为空字符串?

26

以下代码生成一个 df

import pandas as pd
from datetime import datetime as dt
import numpy as np

dates = [dt(2014, 1, 2, 2), dt(2014, 1, 2, 3), dt(2014, 1, 2, 4), None]
strings1 = ['A', 'B',None, 'C']
strings2 = [None, 'B','C', 'C']
strings3 = ['A', 'B','C', None]
vals = [1.,2.,np.nan, 4.]
df = pd.DataFrame(dict(zip(['A','B','C','D','E'],
                           [strings1, dates, strings2, strings3, vals])))



+---+------+---------------------+------+------+-----+
|   |  A   |          B          |  C   |  D   |  E  |
+---+------+---------------------+------+------+-----+
| 0 | A    | 2014-01-02 02:00:00 | None | A    | 1   |
| 1 | B    | 2014-01-02 03:00:00 | B    | B    | 2   |
| 2 | None | 2014-01-02 04:00:00 | C    | C    | NaN |
| 3 | C    | NaT                 | C    | None | 4   |
+---+------+---------------------+------+------+-----+

我想要将所有实际的Python None(而不是字符串)替换为''(空字符串)。

期望 df 是:

+---+---+---------------------+---+---+-----+
|   | A |          B          | C | D |  E  |
+---+---+---------------------+---+---+-----+
| 0 | A | 2014-01-02 02:00:00 |   | A | 1   |
| 1 | B | 2014-01-02 03:00:00 | B | B | 2   |
| 2 |   | 2014-01-02 04:00:00 | C | C | NaN |
| 3 | C | NaT                 | C |   | 4   |
+---+---+---------------------+---+---+-----+

我做的是

df = df.replace([None], [''], regex=True)

但是我得到了

+---+---+---------------------+---+------+---+
|   | A |          B          | C |  D   | E |
+---+---+---------------------+---+------+---+
| 0 | A | 1388628000000000000 |   | A    | 1 |
| 1 | B | 1388631600000000000 | B | B    | 2 |
| 2 |   | 1388635200000000000 | C | C    |   |
| 3 | C |                     | C |      | 4 |
+---+---+---------------------+---+------+---+

  1. 所有的日期都变成了大数字
  2. 甚至连 NaTNaN 都被替换了,可我并不想要这样。

我该如何正确且高效地实现此目标?

5个回答

36

这已经足够了

df.fillna("",inplace=True)
df
Out[142]: 
   A                    B  C  D  E
0  A  2014-01-02 02:00:00     A  1
1  B  2014-01-02 03:00:00  B  B  2
2     2014-01-02 04:00:00  C  C   
3  C                       C     4

编辑2021-07-26:在@dWitty的评论后完成了完整的回应

如果您真的想在文本以外的其他地方保留Nat和NaN值,则只需要为文本列填充Na。在您的示例中,这是A、C、D。

您只需发送一个替换字典给您的列。对于每个列,值可以是不同的。对于您的情况,您只需要构建该字典即可。

# default values to replace NA (None)
# values = {"A": "", "C": "", "D": ""}
values = (dict([[e,""] for e in ['A','C','D']]))
df.fillna(value=values, inplace=True)
df
Out[142]: 
   A                   B  C  D    E
0  A 2014-01-02 02:00:00     A  1.0
1  B 2014-01-02 03:00:00  B  B  2.0
2    2014-01-02 04:00:00  C  C  NaN
3  C                 NaT  C     4.0

1
这应该是答案。 - Tian
问题明确要求仅替换None,而不是任何NaN。 - dWitty

16

看起来None会被转换成NaN,所以你不能像平常一样使用replace,下面的方法可以正常工作:

看起来None会被转换成NaN,所以你不能像平常一样使用replace,下面的方法可以正常工作:
In [126]:
mask = df.applymap(lambda x: x is None)
cols = df.columns[(mask).any()]
for col in df[cols]:
    df.loc[mask[col], col] = ''
df

Out[126]:
   A                   B  C  D   E
0  A 2014-01-02 02:00:00     A   1
1  B 2014-01-02 03:00:00  B  B   2
2    2014-01-02 04:00:00  C  C NaN
3  C                 NaT  C      4

通过使用applymap,我们生成了一个None值的掩码,然后使用这个掩码遍历每个感兴趣的列,并使用布尔掩码设置值。


6

由于您希望更改的相关列都是对象,因此您可以使用dtype属性(为了完整性,我添加了字符串和Unicode)指定这一点,并使用fillna

所以:

for c in df:
   if str(df[c].dtype) in ('object', 'string_', 'unicode_'):
        df[c].fillna(value='', inplace=True)

这将不影响数字和日期列。
要查看所有列的数据类型:
df.dtypes 

3

您可以使用 replace 方法。它可以正常工作。

df.replace('', np.nan, inplace=True)

Source


2

对于那些试图替换 None 而不仅仅是 np.nan 的人(这在这里已经涉及到了)

default_value = ""
df.apply(lambda x: x if x is not None else default_value)

这里是一个简洁的一行代码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接