パンダの空白値(空白)をNaNで置き換える


150

空白(任意の量)を含むPandasデータフレーム内のすべての値を検索し、それらの値をNaNで置き換えたい。

これを改善する方法はありますか?

基本的に私はこれを変えたいです:

                   A    B    C
2000-01-01 -0.532681  foo    0
2000-01-02  1.490752  bar    1
2000-01-03 -1.387326  foo    2
2000-01-04  0.814772  baz     
2000-01-05 -0.222552         4
2000-01-06 -1.176781  qux     

これに:

                   A     B     C
2000-01-01 -0.532681   foo     0
2000-01-02  1.490752   bar     1
2000-01-03 -1.387326   foo     2
2000-01-04  0.814772   baz   NaN
2000-01-05 -0.222552   NaN     4
2000-01-06 -1.176781   qux   NaN

以下のコードでなんとかできましたが、醜いです。Pythonicではなく、パンダの最も効率的な使用法でもないと私は確信しています。各列をループし、空白に一致する各値の正規表現検索を実行する関数を適用して生成された列マスクに対してブール値の置換を行います。

for i in df.columns:
    df[i][df[i].apply(lambda i: True if re.search('^\s*$', str(i)) else False)]=None

空の文字列を含む可能性のあるフィールドを反復するだけで、少し最適化できます。

if df[i].dtype == np.dtype('object')

しかし、それはあまり改善されていません

そして最後に、このコードはターゲット文字列をNoneに設定します。これはのようなPandasの関数で機能しますがfillna()、実際にのNaN代わりに直接を挿入できれば完全性のために良いでしょうNone


2
あなたが本当に望んでいるのはreplace、正規表現で使用できるようにすることです...(おそらくこれは機能としてリクエストする必要があります)。
アンディヘイデン、

3
この機能のgithubの問題を作成しました:github.com/pydata/pandas/issues/2285。広報に感謝します!:)
Chang She

正確に1つの空白文字を欠落させたい場合は、以下の簡単な解決策を
Ted Petrou

回答:


198

パンダ0.13df.replace()以来、私は仕事をすると思います:

df = pd.DataFrame([
    [-0.532681, 'foo', 0],
    [1.490752, 'bar', 1],
    [-1.387326, 'foo', 2],
    [0.814772, 'baz', ' '],     
    [-0.222552, '   ', 4],
    [-1.176781,  'qux', '  '],         
], columns='A B C'.split(), index=pd.date_range('2000-01-01','2000-01-06'))

# replace field that's entirely space (or empty) with NaN
print(df.replace(r'^\s*$', np.nan, regex=True))

生成する:

                   A    B   C
2000-01-01 -0.532681  foo   0
2000-01-02  1.490752  bar   1
2000-01-03 -1.387326  foo   2
2000-01-04  0.814772  baz NaN
2000-01-05 -0.222552  NaN   4
2000-01-06 -1.176781  qux NaN

Temakはそれを指摘し、使用df.replace(r'^\s+$', np.nan, regex=True)する場合には、あなたの有効なデータは空白が含まれています。


1
regexはブールフラグです。たぶん、あなたは意味pd.Series(["1", "#", "9", " .", None]).replace(r"( +\.)|#", "X", regex=True).values与える['1', 'X', '9', 'X', None]
patricksurry

2
2年後、パンダがサポートするようになったので、これに対する受け入れられる回答を変更しました。ありがとう!
Chris Clark、

35
:あなたが途中でスペースを含む要素がNaNの使用と交換することにしたくない場合df.replace(r'^\s+$', np.nan, regex=True)
Temak

7
私はこれを使おうとしましたが、r '^ \ s * $'が使用する式であることがわかりました。^と$を使用しない場合、2つの連続する空白を持つ任意の文字列に一致します。また、+を*に変更して、NaNに変換するもののリストに空の文字列 ""を含める
Master Yogurt

1
私は私のコードであなたの解決策を試していますが、効果はありません。「energy ["Energy Supply"]。replace(to_replace = "..."、value = np.NaN)」を試しています。文字列 "..."をNaN値に変更したいが、何もせず、同じデータフレームを返す。
Archan Joshi

49

空の文字列とレコードをスペースのみで置き換える場合、正解は!:

df = df.replace(r'^\s*$', np.nan, regex=True)

受け入れられた答え

df.replace(r'\s+', np.nan, regex=True)

空の文字列を置き換えません!、わずかに更新された所定の例を試すことができます:

df = pd.DataFrame([
    [-0.532681, 'foo', 0],
    [1.490752, 'bar', 1],
    [-1.387326, 'fo o', 2],
    [0.814772, 'baz', ' '],     
    [-0.222552, '   ', 4],
    [-1.176781,  'qux', ''],         
], columns='A B C'.split(), index=pd.date_range('2000-01-01','2000-01-06'))

また、 'fo o'にはスペースが含まれていますが、Nanに置き換えられていません。さらに、簡単なことに注意してください。

df.replace(r'', np.NaN)

どちらも機能しません-試してみてください。


33

どうですか:

d = d.applymap(lambda x: np.nan if isinstance(x, basestring) and x.isspace() else x)

applymap関数は、データフレームのすべてのセルに関数を適用します。


なんて素晴らしい改善でしょう!私はこれを振り返って考えるべきだったのですが、なんらかの理由でブール値の置換を行うことに夢中になりました。1つの質問-基本文字列チェックを実行することに対して、str(x).isspace()だけを実行するよりもメリットがありますか?
Chris Clark、

1
@ChrisClark:どちらかで構いませisinstanceんが、少し速くなると思います。
BrenBarn、

13
上記のコードの「basestring」への参照は、Python 3 ....では機能しません。その場合は、代わりに「str」を使用してみてください。
スパイクウィリアムズ

4
このソリューションは空の文字列を置き換えないことに注意してください''。:また、空の文字列を、使用を検討するにはd = d.applymap(lambda x: np.nan if isinstance(x, basestring) and (not x or x.isspace()) else x)
tuomastik

18

私はこれを行います:

df = df.apply(lambda x: x.str.strip()).replace('', np.nan)

または

df = df.apply(lambda x: x.str.strip() if isinstance(x, str) else x).replace('', np.nan)

すべてのstrを削除してから、空のstrをに置き換えることができますnp.nan


ラムダx:x.str.strip()はラムダx:x.strip()である必要がありますか?マイナーな提案:前に.astype(str)を追加します。これにより、他のデータ問題が解決されます。これは私にとってはうまくいきます:df = df.apply ['column']。astype(str).apply(lambda x:x.strip())。replace( ''、np.nan)
Wouter

コードの2行目は、int / float型と文字列型の両方の列を処理します。いいね。Tks!
Kate Stohr


5

CSVファイルからデータをエクスポートする場合は、次のように簡単です。

df = pd.read_csv(file_csv, na_values=' ')

これにより、データフレームが作成され、空白値がNaに置き換えられます。


2
別のオプション..using skipinitialspace=Trueも、区切り文字の後の空白を削除します。これにより、任意の長さの空白、空の文字列がとして読み取られnanます。ただし、何らかの理由で初期スペースを保持したい場合は、このオプションは適切な選択ではありません。
Rajshekar Reddy 2018

1
@RajshekarReddyこれを答えとしてどこかに入れてください、これは素晴らしいものでした!
User2321

2

単一の値と等しいかどうかを確認する非常に高速でシンプルなソリューションの場合、このmaskメソッドを使用できます。

df.mask(df == ' ')

1

これらはすべて正しい答えに近いものですが、コードを読んでいる他の人が最も読みやすいまま、問題を解決することはできません。その答えは、BrenBarnの回答とその回答の下のtuomasttikのコメント組み合わせだと思います。ブレンバーンの答えはisspace組み込みをしていますが、OPが要求したように空の文字列を削除することはサポートしていません。

で書き直した.applyので、pd.Seriesまたはで呼び出すことができますpd.DataFrame


Python 3:

空の文字列または完全にスペースの文字列を置き換えるには:

df = df.apply(lambda x: np.nan if isinstance(x, str) and (x.isspace() or not x) else x)

完全にスペースの文字列を置き換えるには:

df = df.apply(lambda x: np.nan if isinstance(x, str) and x.isspace() else x)

Pythonの2にこれを使用するには、交換する必要がありますstrbasestring

Python 2:

空の文字列または完全にスペースの文字列を置き換えるには:

df = df.apply(lambda x: np.nan if isinstance(x, basestring) and (x.isspace() or not x) else x)

完全にスペースの文字列を置き換えるには:

df = df.apply(lambda x: np.nan if isinstance(x, basestring) and x.isspace() else x)

1

これでうまくいきました。csvファイルをインポートするときに、na_values = ''を追加しました。スペースは、デフォルトのNaN値には含まれません。

df = pd.read_csv(filepath、na_values = '')


0

フィルターを使用して行うこともできます。

df = PD.DataFrame([
    [-0.532681, 'foo', 0],
    [1.490752, 'bar', 1],
    [-1.387326, 'foo', 2],
    [0.814772, 'baz', ' '],     
    [-0.222552, '   ', 4],
    [-1.176781,  'qux', '  '])
    df[df=='']='nan'
    df=df.astype(float)

このコードのすべての行(データを含まない)に障害があります。
ジュリアス

0
print(df.isnull().sum()) # check numbers of null value in each column

modifiedDf=df.fillna("NaN") # Replace empty/null values with "NaN"

# modifiedDf = fd.dropna() # Remove rows with empty values

print(modifiedDf.isnull().sum()) # check numbers of null value in each column

0

これはエレガントなソリューションではありませんが、動作すると思われるのはXLSXに保存してからインポートし直すことです。このページの他の解決策は私にはうまくいきませんでした。理由は不明です。

data.to_excel(filepath, index=False)
data = pd.read_excel(filepath)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.