イケてるタイトルがつけられなくて申し訳ない。
pandas.to_numeric という関数の errors という引数が便利なことを知ったのでそれを紹介します。
データを扱っている時、文字列型の数字を数値型に型変換したいことはよくあります。
単体の変数であれば、 int
やflaot
で変換できます。
int("123") #123
float("123") # 123.0
DataFrameや Series でも、全ての値が問題なく変換できる場合は、 .astype
で変換できます。
data1_str = pd.Series(["1", "2", "3"])
print(data1_str)
"""
0 1
1 2
2 3
dtype: object
"""
data1_int = data1_str.astype(int)
print(data1_int)
"""
0 1
1 2
2 3
dtype: int64
"""
ここで厄介なのが、元の値の中に、欠損値や数値に変換できない値が混ざっている場合です。
.astype(int)
や .astype(float)
すると、エラーが発生します。
astypeメソッド自体も、errorという引数をとりますが、
エラーを ignore で抑制した場合、変換は一切行ってくれません。
参考: pandas.Series.astype
僕が期待しているのは、 数値型に変換できる値は数値型に変換して、Noneや変換できない文字列は NaNで埋めてくれることです。
そして、それが、pandas.to_numericを使うと手軽に実現できます。
import pandas as pd
# ダミーデータ生成
df = pd.DataFrame(
{
"key": ["key1", "key2", "key3", "key4"],
"value_str": ["123", "45.67", None, "八十九"],
}
)
# value_str 列の値を数値に変えられるものは変えた列を作る
df["value_num"] = pd.to_numeric(df["value_str"], errors="coerce")
print(df)
"""
key value_str value_num
0 key1 123 123.00
1 key2 45.67 45.67
2 key3 None NaN
3 key4 八十九 NaN
"""
バッチリできました。
ポイントは、 errors="coerce"
の部分です。
errorsは、”ignore”, “raise”, “coerce” の3種類の値を取ります。
“raise” がデフォルトで、これを指定すると普通に例外が発生します。
“ignore” は例外を抑えますが、何の変換もせず、そのままのオブジェクトを返します。
“coerce” は、数値に変換できるものは変換して、そうでないものはNaNにしてくれます。
“raise”だとこのような例外が発生します。
try:
pd.to_numeric(df["value_str"], errors="raise")
except Exception as e:
print(e)
# Unable to parse string "八十九" at position 3
文字列を時刻に変える to_datetime や、汎用的な型変換の astype に比べてマイナーな印象があるのですが、
地味に使える場面が多いので、数値への型変換の機会があったら、
to_numeric を試してみてください。