観測データ等をpandasで取り扱う場合に欠測値等が文字列になっていることがよくあります。
この処理が結構苦労するのですが、現時点での最良案をまとめます。
もっと良い方法があれば教えて下さい。
サンプルデータ
サンプルデータは以下の気象庁の公開データの形式とする。準正常値の場合は)が後ろに付きます。
import pandas as pd import numpy as np
df = pd.DataFrame({'A': [29.0, 26.5, 28.9, 33.1, '30.0 )'], 'B': [31.3, 31.3, 32.4, 32.1, 34.3], 'C': [ 29.5, 27.7, 32.5, '30.3 )', 26.1]}) df
A | B | C | |
---|---|---|---|
0 | 29.0 | 31.3 | 29.5 |
1 | 26.5 | 31.3 | 27.7 |
2 | 28.9 | 32.4 | 32.5 |
3 | 33.1 | 32.1 | 30.3 ) |
4 | 30.0 ) | 34.3 | 26.1 |
数値に変換できない列を抽出
dfp = df.select_dtypes(include='object')
dfp
A | C | |
---|---|---|
0 | 29.0 | 29.5 |
1 | 26.5 | 27.7 |
2 | 28.9 | 32.5 |
3 | 33.1 | 30.3 ) |
4 | 30.0 ) | 26.1 |
エラー値を抽出
手順は以下のとおりです。
- データを文字列に変換
- 正規表現により文字列の要素を抽出。正規表現は、[解決!Python]文字列が数値へ変換可能かどうかを判定するには(int/float関数の例外、re.fullmatch関数):解決!Python - @ITを参照
- 文字列要素からユニークな要素のみをリスト化する。
dfp = dfp.astype(str) p = '[-+]?(\d+\.?\d*|\.\d+)([eE][-+]?\d+)?' out = np.empty(0) for n in dfp.columns: #数字以外の文字を抽出 a = dfp[dfp[n].str.fullmatch(p)==False][n].values out = np.append( out, np.unique(a) ) out = np.unique(out) out
array(['30.0 )', '30.3 )'], dtype=object)
エラー値の処理方法を考える
今回は、通常の数値と同様に取り扱うため、カッコを削除して数値に変換します。
for n in out : nn = float( n.replace(')','').strip() ) df = df.replace(n, nn) df
A | B | C | |
---|---|---|---|
0 | 29.0 | 31.3 | 29.5 |
1 | 26.5 | 31.3 | 27.7 |
2 | 28.9 | 32.4 | 32.5 |
3 | 33.1 | 32.1 | 30.3 |
4 | 30.0 | 34.3 | 26.1 |
# 数値に戻す df= df.astype(float)
df.dtypes
A float64
B float64
C float64
dtype: object
- ちなみに、nanに置換する場合は以下のとおりです。
for n in out : df = df.replace(n, np.nan)