bugfix> python > 投稿

非常に大きなデータフレーム(数千×数千)があり、ここでは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

これらは他のデバイスから来ているため(dfは pd.read_csv(filename) によって生成されます )完全に float である代わりにデータフレームタイプは、 +unend のような不要な文字列を持つことになりますおよび n. def. 。これらは古典的な +infinity ではありませんまたは NaN 、その df.fillna() 気をつけてください。文字列を 0.0 に置き換えたい 。これらの答えを見ましたパンダがタイプの問題を置き換える そしてパンダのデータフレームの文字列を置き換えます 同じことをしようとしていますが、列または行単位ですが、要素単位ではありません。ただし、コメントには、一般的なケースでも同様の手続きを行うための良いヒントがありました。

しようとしたら

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 ではなくregexをチェックに使用できるかどうかわかりません 、特に、データ型が混在していることがわかっている場合。これを行うための効率的、高速、堅牢な要素ごとの一般的な方法はありますか?

回答 3 件
  • 先のとがった Edchum  すべての非数値を 0 に置き換える必要がある場合  -最初の to_numeric   errors='coerce' と   NaN を作成 s解析不能な値の場合、それらを 0 に変換します  によって 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 の場合  定義値:

    特別な正規表現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
    
    

  • These are not the classical +infinity or NaN , that df.fillna() could take care off

    NA と見なす文字列のリストを指定できます  csvファイルを読み取るとき。

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

    そして、 NA を埋めます   fillna の値

  • 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)
    
    

あなたの答え