如何在 Pandas DataFrame 中用 NaN 替换整个单元格

4
我希望用空白或NaN替换包含图片中所圈出单词的整个单元格。但是,当我尝试替换例如“1.25 Dividend”时,结果变成了“1.25 NaN”。我希望返回整个单元格为“NaN”。有什么想法吗?
3个回答

5

选项一
在替换过程中使用正则表达式。

df.replace('^.*Dividend.*$', np.nan, regex=True)

来自评论

使用regex=True意味着它将把问题解释为正则表达式。 您仍然需要一个合适的模式。 '^'表示从字符串开头开始匹配。 '^.*'匹配字符串开头的所有字符。 '$'表示将匹配结束于字符串的结尾。 '.*$'匹配到字符串结尾的所有字符。 最后,'^.*Dividend.*$'匹配字符串开头的所有字符,中间有'Dividend',之后跟任何字符。 然后用np.nan替换整个内容。

考虑数据框df

df = pd.DataFrame([[1, '2 Dividend'], [3, 4], [5, '6 Dividend']])
df

   0           1
0  1  2 Dividend
1  3           4
2  5  6 Dividend

那么提出的解决方案就会产生

   0    1
0  1  NaN
1  3  4.0
2  5  NaN

选项2
另一种选择是将pd.DataFrame.maskapplymap结合使用。
如果我向applymap传递一个lambda,它可以识别任何单元格中是否有'Dividend'

df.mask(df.applymap(lambda s: 'Dividend' in s if isinstance(s, str) else False))

   0    1
0  1  NaN
1  3    4
2  5  NaN

选项3
这个概念类似,但是使用stack/unstack+ pd.Series.str.contains

df.mask(df.stack().astype(str).str.contains('Dividend').unstack())

   0    1
0  1  NaN
1  3    4
2  5  NaN

1
如果您不想显式导入numpy,则pd.np.nan也会产生相同的结果。 - TrigonaMinima
嗨,它有效了!起初我将正则表达式设置为False。这意味着如果我们将正则表达式设置为True,它会替换整个单元格? - Ha An Tran
@HaAnTran 不是这样的!它意味着将问题解释为正则表达式。你仍然需要一个适当的模式。'^' 表示从字符串开头开始匹配。'^.*' 匹配从字符串开头开始的所有字符。'$' 表示在字符串结尾处结束匹配。'.*$' 匹配直到字符串结尾的所有字符。最后,'^.*Dividend.*$' 匹配从开头开始的所有字符,在中间有 'Dividend',然后是任何字符。然后用 np.nan 替换整个内容。 - piRSquared

0

替换所有字符串:

df.apply(lambda x: pd.to_numeric(x, errors='coerce'))

如果单元格是字符串,而且 OP 想要保持它们为字符串怎么办?OP 要求替换被除数单元格。你可以修改为 df.mask(df.apply(lambda x: pd.to_numeric(x, errors='coerce')).isnull()),但这样会遇到一个问题,它也会掩盖任何其他字符串单元格,比如 CashShares 或其他任何单元格。 - piRSquared

0
我会像这样使用 applymap。
df.applymap(lambda x: 'NaN' if (type(x) is str and 'Dividend' in x) else x)

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