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


80

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

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、私はデータフレームは、このようなひどいやり方で動作する理由を知りたいです。

Python2.7およびOSX10.8のパンダ0.12.0devでテスト済み。PythonはOSXにプリインストールされているバージョンであり、参考までに、SciPySuperpackスクリプトを使用してパンダをインストールしました。


sをsにwrite_frame解析しませんか?NaNnone
Andy Hayden 2013年

うん。InternalError: (1054, u"Unknown column 'nan' in 'field list'")エラーが発生します。メソッドを実行NaNするNone前に変換する以外の解決策についてはわかりませんwrite_frame
ブラザード2013年

どのバージョンのパンダを使用していますか?
Andy Hayden

Scipyスーパーパックは開発者を配りますか?わかりました。これをgithubの問題として提起する必要があると思いますが、修正するのはそれほど難しいことではありません。
Andy Hayden

このデータをCSV / Excelから読み取る場合はna_values引数を使用してこれらの値をNaNとして読み取ることができます。この回答の詳細。
cs 9519

回答:


111

実際、パンダの新しいバージョンでは、これにより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

ただし、Noneではなく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

15
または単にリスト、例えばdf.replace(['-'], [None])、またはdf.replace({'-': None})、私は思います。使用Noneすぎる値としてそれを使用してセンチネル妨げるよう..
DSM

@ user2360798 replaceは実際には非常に機能豊富な(複雑な読み取り)関数ですが、(dev)docstringは本当に優れています。
Andy Hayden 2013年

4
私はそれは明らかだ場合は知っているが、割り当てるために持っていたしませんdfようにそれ自体に戻っ:df = df.replace({'?': np.nan})
luckyging3r

3
@AndyHaydendf.replace('-', df.replace(['-'], [None])はファンキーに見えますが、それはタイプミスですか?
lin_bug 2017年

2
@lin_bug最近のパンダバージョンでは機能しなくなったようですが。df.where(df!= '-'、None)は機能します
Andy Hayden

17

私が使用したソリューションを好むreplacedictそのシンプルさと優雅さのために:

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

さらに多くの代替品を用意することもできます。

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

そして、より大きな置換の場合でも、何が何に置き換えられるかは常に明白で明確です-これは、私の意見では、長いリストでははるかに困難です。


1
この手法が機能する理由の一部は、dictin型を使用to_replaceするとmethodパラメーターが評価されないため、method='pad'デフォルトでは悪影響がないことです。
bsplosion

15

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

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

パンダのドキュメントから:

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


5
これは実際には不正確です。data = data.where(data == '-'、None)は、 '-'と等しくないものをNoneに置き換えます。パンダバージョンのwhereは、最初の引数(この場合はdata == '-')の値を保持し、それ以外は2番目の引数(この場合はNone)に置き換えます。np.whereは、最初の引数で条件付き、2番目の引数でif true、3番目の引数でif falseを要求するという点で、より明示的であるため、少し混乱します。
clg4 2017

8

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

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

しかし、あなたの質問に答えるために...

pandas> = 0.18:na_values=['-']引数を使用するread_csv

このデータを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

そして、他の関数/ファイル形式についても同様です。

PS: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整数型です。他のオプションがあります。


数値データの処理:pd.to_numericwitherrors='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

(null許容)整数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

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

詳細については、この回答をご覧ください。



0

null値の設定は、次の方法で実行できますnp.nan

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

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


0

replaceを使用して、新しいdfを割り当てます。

import pandas as pd
df = pd.DataFrame(['-',3,2,5,1,-5,-1,'-',9])
dfnew = df.replace('-', 0)
print(dfnew)


(venv) D:\assets>py teste2.py
   0
0  0
1  3
2  2
3  5
4  1
5 -5

0
df.replace('-', np.nan).astype("object")

これisnull()により、後でデータフレームで使用できるようになります


0

Pandasバージョン≥1.0.0では、DataFrame.replaceまたはSeries.replace:を使用します。

df.replace(old_val, pd.NA, inplace=True)

これは2つの理由でより良いです:

  1. またはのpd.NA代わりに使用します。Nonenp.nan
  2. これは、メモリ効率を高める可能性のあるインプレースの値置き換えます。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.