代码之家  ›  专栏  ›  技术社区  ›  Vipluv

以明智和高效的方式替换pandas数据帧元素中不需要的字符串

  •  1
  • Vipluv  · 技术社区  · 7 年前

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

                                      col1                col2             col3
    time                                                                         
    05/04/2018 05:14:52 AM             +unend           +unend                  0
    05/04/2018 05:14:57 AM                 0                 0                  0
    05/04/2018 05:15:02 AM            30.691             0.000              0.121
    05/04/2018 05:15:07 AM            30.691             n. def.            0.108
    05/04/2018 05:15:12 AM            30.715             0.000              0.105
    

    pd.read_csv(filename) )数据帧而不是完全 float 现在输入的结果是有不需要的字符串,比如 +unend n. def. 。这些不是古典的 +infinity NaN ,那 df.fillna() 可以照顾好。我想把弦换成 0.0 。我看到了这些答案 Pandas replace type issue replace 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的序列对象,而不是一个elementwise掩码,因此会出现一个错误。 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?)另外,我不确定是否可以使用regex进行检查,而不是 in 尤其是,如果我知道数据类型是混合的。有没有一个有效的,快速的,强大的,但同时也是元素方面的一般方法来做到这一点?

    3 回复  |  直到 7 年前
        1
  •  0
  •   jezrael    7 年前

    如图所示 Edchum 如果需要,将所有非数字值替换为 0 -第一个 to_numeric 具有 errors='coerce' 创造 NaN s表示不可解析的值,然后将其转换为 通过 fillna :

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

    如果值不是 substring S使用 DataFrame.isin 或者很好的回答 Haleemur Ali :

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

    对于 substrings 定义值:

    有特殊的regex char + . ,所以需要逃离他们 \ :

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

    或使用 applymap 电子检查:

    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
  •  5
  •   Haleemur Ali    7 年前

    这些不是df.fillna()可以处理的经典+无穷大或NaN。

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

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

    然后填充 值与 fillna

        3
  •  0
  •   jpp    7 年前

    不要使用pd.series.str.contains或pd.series.isin

    解决这个问题的一个更有效的方法是 pd.to_numeric 要转换,请尝试将所有数据转换为数字。

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

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