【问题标题】:Replace empty list values in Pandas DataFrame with NaN用 NaN 替换 Pandas DataFrame 中的空列表值
【发布时间】:2017-05-04 17:02:02
【问题描述】:

我知道以前有人问过类似的问题,但我尝试了这里列出的所有可能的解决方案,但都没有奏效。

我有一个由日期、字符串、空值和空列表值组成的数据框。它非常巨大,有 800 万行。

我想替换所有空列表值 - 所以只有包含 [] 的单元格,没有其他包含 NaN 的单元格。似乎没有任何效果。

我试过了:

df = df.apply(lambda y: np.nan if (type(y) == list and len(y) == 0) else y)

正如这个问题replace empty list with NaN in pandas dataframe 中的类似建议,但它不会改变我的数据框中的任何内容。

任何帮助将不胜感激。

【问题讨论】:

  • 我认为这可能不是您的代码的问题。您可以检查列的真实数据类型。也许它默认为object
  • 您是空列表字符串'[]' 还是实际的空列表?

标签: python-3.x pandas dataframe


【解决方案1】:

我将假设您要屏蔽实际的空列表。

  • pd.DataFrame.mask 会将具有相应 True 值的单元格转换为 np.nan
  • 我想找到实际的list 值。所以我将使用df.applymap(type) 来获取每个单元格中的类型,看看它是否等于list
  • 我知道[] 在布尔上下文中的计算结果为False,所以我将使用df.astype(bool) 来查看。
  • 我最终会屏蔽那些既是list 类型又评估为False 的单元格

考虑数据框df

df = pd.DataFrame([
        [1, 'hello', np.nan, None, 3.14],
        ['2017-06-30', 2, 'a', 'b', []],
        [pd.to_datetime('2016-08-14'), 'x', '[]', 'z', 'w']
    ])

df

                     0      1    2     3     4
0                    1  hello  NaN  None  3.14
1           2017-06-30      2    a     b    []
2  2016-08-14 00:00:00      x   []     z     w

解决方案

df.mask(df.applymap(type).eq(list) & ~df.astype(bool))

                     0      1    2     3     4
0                    1  hello  NaN  None  3.14
1           2017-06-30      2    a     b   NaN
2  2016-08-14 00:00:00      x   []     z     w

【讨论】:

  • 这很好,它有效,但@Allen 是对的,我需要将它们全部转换为 NaN,所以我会标记他的答案。
【解决方案2】:

假设OP想要将空列表,字符串'[]'和对象'[]'转换为na,下面是一个解决方案。

设置

#borrowed from piRSquared's answer.
df = pd.DataFrame([
        [1, 'hello', np.nan, None, 3.14],
        ['2017-06-30', 2, 'a', 'b', []],
        [pd.to_datetime('2016-08-14'), 'x', '[]', 'z', 'w']
    ])

df
Out[1062]: 
                     0      1    2     3     4
0                    1  hello  NaN  None  3.14
1           2017-06-30      2    a     b    []
2  2016-08-14 00:00:00      x   []     z     w

解决方案:

#convert all elements to string first, and then compare with '[]'. Finally use mask function to mark '[]' as na
df.mask(df.applymap(str).eq('[]'))
Out[1063]: 
                     0      1    2     3     4
0                    1  hello  NaN  None  3.14
1           2017-06-30      2    a     b   NaN
2  2016-08-14 00:00:00      x  NaN     z     w

【讨论】:

  • 谢谢,是的,我想将它们全部转换为 NaN。你对性能有什么建议吗?它在 800 万行上很慢。可以改进吗?
猜你喜欢
  • 2013-09-12
  • 2018-11-14
  • 2017-07-04
  • 1970-01-01
  • 2016-01-08
  • 2023-01-19
  • 1970-01-01
相关资源
最近更新 更多