web-dev-qa-db-ja.com

Pandas DataFrameで無効な値をNoneに置き換えます

PythonでPandasの値をNoneに置き換える方法はありますか?

df.replace('pre', 'post')を使用して値を別の値に置き換えることができますが、Noneの値で置き換えたい場合、これを行うことはできません。

以下に例を示します。

df = DataFrame(['-',3,2,5,1,-5,-1,'-',9])
df.replace('-', 0)

成功した結果を返します。

しかし、

df.replace('-', None)

次の結果が返されます。

0
0   - // this isn't replaced
1   3
2   2
3   5
4   1
5  -5
6  -1
7  -1 // this is changed to `-1`...
8   9

なぜこのような奇妙な結果が返されるのですか?

このデータフレームをMySQLデータベースに注ぎたいので、NaN値をデータフレームの要素に入れることができず、代わりにNoneを入れたいです。確かに、最初に'-'NaNに変更してからNaNNoneに変換できますが、データフレームがこのようにひどい動作をする理由を知りたいです。

pandas 0.12.0 dev Python 2.7およびOS X 10.8でテスト済み。 PythonはOS Xにプリインストールされたバージョンであり、情報としてSciPy Superpackスクリプトを使用してpandasをインストールしました。

64
Blaszard

実際、pandasの後のバージョンでは、TypeErrorが発生します:

df.replace('-', None)
TypeError: If "to_replace" and "value" are both None then regex must be a mapping

リストまたは辞書を渡すことでそれを行うことができます:

In [11]: df.replace('-', df.replace(['-'], [None]) # or .replace('-', {0: None})
Out[11]:
      0
0  None
1     3
2     2
3     5
4     1
5    -5
6    -1
7  None
8     9

ただし、なしではなくNaNを使用することをお勧めします。

In [12]: df.replace('-', np.nan)
Out[12]:
     0
0  NaN
1    3
2    2
3    5
4    1
5   -5
6   -1
7  NaN
8    9
88
Andy Hayden

whereはおそらくあなたが探しているものです。そう

data=data.where(data=='-', None) 

panda docs から:

where [戻り] selfと同じ形状のオブジェクトで、対応するエントリがcondがTrueである場合はselfからのものであり、そうでない場合はotherからのものです。

14
user2966041

replacedictとともに使用するソリューションは、そのシンプルさと優雅さから好まれます。

df.replace({'-': None})

また、より多くの代替品を持つことができます:

df.replace({'-': None, 'None': None})

そして、大規模な代替品であっても、何が何によって代替されるかは常に明白で明確です-私の意見では、これは長いリストにとってははるかに困難です。

11
Michael Dorner

この投稿を進める前に、 NaNとNoneの違い を理解することが重要です。 1つはfloat型で、もう1つはオブジェクト型です。 Pandasは、これらの型の多くのメソッドをベクトル化できるため、スカラー型の操作により適しています。 PandasはNoneとNaNを一貫して処理しようとしますが、NumPyは処理できません。

私の提案( およびAndy's )は、NaNに固執することです。

(v0.24 +)CSV/Excelデータのより良いソリューション:na_values=['-']

CSV/Excelからこのデータを読み込んだ場合、良いニュースがあります。後続のステップとしてコードで修正を書く代わりに、データのロード中にルートでこれを無効にすることができます。

ほとんどのpd.read_*関数( read_csvread_Excel など)は、na_values属性を受け入れます。

file.csv

A,B
-,1
3,-
2,-
5,3
1,-2
-5,4
-1,-1
-,0
9,0

ここで、-文字をNaNに変換するには、次のようにします。

import pandas as pd
df = pd.read_csv('file.csv', na_values=['-'])
df

     A    B
0  NaN  1.0
1  3.0  NaN
2  2.0  NaN
3  5.0  3.0
4  1.0 -2.0
5 -5.0  4.0
6 -1.0 -1.0
7  NaN  0.0
8  9.0  0.0

他の関数/ファイル形式でも同様です。

追伸:v0.24 +では、列にNaNが含まれていても整数型を保持できます(はい、ケーキを食べて食べることについても話してください)。 dtype='Int32'を指定できます

df = pd.read_csv('file.csv', na_values=['-'], dtype='Int32')
df

     A    B
0  NaN    1
1    3  NaN
2    2  NaN
3    5    3
4    1   -2
5   -5    4
6   -1   -1
7  NaN    0
8    9    0

df.dtypes

A    Int32
B    Int32
dtype: object

Dtypeは従来のint型ではなく... Nullable Integer Type。 他のオプションがあります。


数値データの処理:pd.to_numericerrors='coerce

数値データを扱う場合、より速い解決策は pd.to_numericerrors='coerce'引数とともに使用することです。これは無効な値(数値にキャストできない値)をNaNに強制します。

pd.to_numeric(df['A'], errors='coerce')

0    NaN
1    3.0
2    2.0
3    5.0
4    1.0
5   -5.0
6   -1.0
7    NaN
8    9.0
Name: A, dtype: float64

(nullable)整数dtypeを保持するには、次を使用します

pd.to_numeric(df['A'], errors='coerce').astype('Int32')

0    NaN
1      3
2      2
3      5
4      1
5     -5
6     -1
7    NaN
8      9
Name: A, dtype: Int32 

複数の列を強制するには、applyを使用します。

df[['A', 'B']].apply(pd.to_numeric, errors='coerce').astype('Int32')

     A    B
0  NaN    1
1    3  NaN
2    2  NaN
3    5    3
4    1   -2
5   -5    4
6   -1   -1
7  NaN    0
8    9    0

...そして結果を後に割り当てます。

詳細は this answer にあります。

3
cs95
df = pd.DataFrame(['-',3,2,5,1,-5,-1,'-',9])
df = df.where(df!='-', None)
2
Shravan kp

ヌル値の設定は、np.nanを使用して実行できます。

import numpy as np
df.replace('-', np.nan)

利点は、df.last_valid_index()がこれらを無効として認識することです。

0