在pandas dataframe元素中明智有效地替换不需要的字符串

时间:2018-05-25 08:03:11

标签: python pandas dataframe

我有一个非常大的数据帧(数千x)只显示5 x 3这里,时间是索引

pd.read_csv(filename)

由于这些来自其他设备(df由float生成),因此数据框而不是完全+unend类型现在最终会出现不需要的字符串,例如n. def.和{{ 1}}。这些不是经典的+infinityNaNdf.fillna()可以解决这些问题。我想用0.0替换字符串。我看到了这些答案Pandas replace type issuereplace string in pandas dataframe虽然尝试做同样的事情,但是列或行是明智的,但不是元素。但是,在评论中,对于一般情况也有一些很好的提示。

如果我尝试

mask = df.apply(lambda x: x.str.contains(r'+unend|n. def.'))
df[mask] =0.0

我得到error: nothing to repeat

如果我这样做

mask = df.apply(lambda x: (str('n. def.') in (str(x)) or (str('unend') in str(x))) )
df[mask]=0.0

我会为每个列而不是元素掩码获得一个True或False的Series对象,因此会出错  TypeError: Cannot do inplace boolean setting on mixed-types with a non np.nan value

以下

mask = df.applymap(lambda x: (str('n. def.') in (str(x)) or (str('unend') in str(x))) )
df[mask.values]=0.0

确实给了我预期的结果用0.0替换所有不需要的字符串但是,它很慢(unpythonic?)而且,我不确定我是否可以使用正则表达式进行检查而不是in,尤其是如果我知道有混合数据类型。有没有一种高效,快速,强大但也是元素的一般方法来做到这一点?

3 个答案:

答案 0 :(得分:5)

  

这些不是经典的+无穷大或NaN,df.fillna()可以解决这个问题

您可以在阅读csv文件时指定要考虑为NA的字符串列表。

df = pd.read_csv(filename, na_values=['+unend', 'n. def.'])

然后使用NA

填充fillna

答案 1 :(得分:0)

如所指示Edchum,如果需要将所有非数字值替换为0 - 首先to_numeric errors='coerce'创建NaN s表示不可解析的值,然后转换他们0fillna

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

如果值不是substring使用DataFrame.isin或非常好的Haleemur Ali答案:

df = df.mask(df.isin(['+unend','n. def.']), 0).astype(float)

对于具有定义值的substrings

有特殊的正则表达式字符+.,因此需要通过\转义它们:

df = df.mask(df.astype(str).apply(lambda x: x.str.contains(r'(\+unend|n\. def\.)')), 0).astype(float)

或使用applymap进行elemnetwise检查:

df = df.mask(df.applymap(lambda x: (str('n. def.') in (str(x)) or (str('unend') in str(x))) ), 0).astype(float)
print (df)
                          col1  col2   col3
time                                       
05/04/2018 05:14:52 AM   0.000   0.0  0.000
05/04/2018 05:14:57 AM   0.000   0.0  0.000
05/04/2018 05:15:02 AM  30.691   0.0  0.121
05/04/2018 05:15:07 AM  30.691   0.0  0.108
05/04/2018 05:15:12 AM  30.715   0.0  0.105

答案 2 :(得分:0)

请勿使用pd.Series.str.contains或pd.Series.isin

解决此问题的更有效方法是使用pd.to_numeric转换try并将所有数据转换为数字。

使用errors='coerce'默认为NaN,然后您可以使用pd.Series.fillna

cols = ['col1', 'col2', 'col3']
df[cols] = df[cols].apply(pd.to_numeric, errors='coerce').fillna(0)