pandasのinfer_objects()は、数字の入った文字列('123')を数値(123)に変換しない、という話。
StackOverflowのURL: https://stackoverflow.com/questions/35003138/python-pandas-inferring-column-datatypes/48269724 のコメント
infer_objects()は、DataFrameのメソッドとSeriesのメソッドと両方がある。
pandas.DataFrame.infer_objectsの関数API:pandas.DataFrame.infer_objects — pandas 0.25.3 documentation
pandas.Series.infer_objectsの関数API:pandas.Series.infer_objects — pandas 0.25.3 documentation
(今後メジャーアップデートが来るから、バージョン指定したURLにしておくよ)
pandasの型システムであるdtypeが分かってないんだよね、という人は、以前dtypeについての公式ドキュメントを翻訳したので是非ご覧ください。
動作環境
python 3.7.6
pandas 0.25.3
StackOverflowの例
上記のStackOverflowのコメントによれば、pd.DataFrame(['1', '2', '3']) にinfer_objects()を適用しても、数値になってくれないらしい。本当だろうか。
df1 = pd.DataFrame(['1', '2', '3']) df1.dtypes
0 object
dtype: object
このデータに対してinfer_objects()を適用する。
df1.infer_objects().dtypes
0 object
dtype: object
本当だ。確かにdtypesはobjectのままだ。
infer_objectsは型を「推測」するだけで「変換」はしない
関数名には、convertという単語は入っていない。
関数名の中にあるinferという単語の和訳は「推測する、推論する」であり、「変換する」ではない。
なるほど、ちゃんと考えてこの関数名にしたんだな、と思える。
公式ドキュメント([https://pandas.pydata.org/pandas-docs/version/0.25.3/reference/api/pandas.Series.infer_objects.html:title])の使用例は、確かに型を推測しているのであり、変換してはいない。
# 公式ドキュメントに載っている例 df2 = pd.DataFrame({"A": ["a", 1, 2, 3]}) df2 = df2.iloc[1:] df2
A | |
---|---|
1 | 1 |
2 | 2 |
3 | 3 |
df2.dtypes
A object
dtype: object
df2.infer_objects().dtypes
A int64
dtype: object
この例だと、最初に作ったDataFrameにa
という文字列が入っていたので、dtypeがobjectに設定された。
数値部分だけを取り出したときも、dtypeは自動的に変換されないので、objectのままだ。
そこでinfer_objects()を適用すると、今あるデータが入る最適な型であるint64が選択された。めでたしめでたし。
なるほど。infer_objects() のやってることが分かったぞ。
じゃあ、全く同じことをやってみよう。ただし、文字列a
ではなく、浮動小数点数を使ってみよう。
# では文字列の代わりに浮動小数点数ではどうだろうか? df3 = pd.DataFrame({"A": [9.876, 1, 2, 3]}) df3 = df3.iloc[1:] df3
A | |
---|---|
1 | 1.0 |
2 | 2.0 |
3 | 3.0 |
df3.dtypes
A float64
dtype: object
df3.infer_objects().dtypes
A float64
dtype: object
えっ。どういうことなの。今あるデータは整数だけなんだから、それが入る適切な型であるint64が出力されるんじゃないの?
infer_objects() 何もわからない。
じゃあ文字列を数字に変換する方法は?
to_numeric()を使いましょう。
pandasで型を推測するときの規則は? よく分からない……
APIリファレンスには以下のように書いてある。
The inference rules are the same as during normal Series/DataFrame construction.
拙訳:推測の規則は、通常のSeries/DataFrameの作成をするときと同じである。
「通常のSeries/DataFrameの作成をするとき」のdtype推論の規則は、どのようなものだろうか?
この疑問の具体的な答えは、pandasドキュメントの中には見つからなかった。
例えば、DataFrameのコンストラクタについてのページ[https://pandas.pydata.org/pandas-docs/version/0.25.3/reference/api/pandas.DataFrame.html:title]では、
「引数dtypeがNoneだったら推測します(infer)」と書いてあるだけだ。具体的にどう推測するかは一切書かれていない。
「通常のSeries/DataFrameの作成をするとき」には、64bitの整数型で収まる場合にはint64型になる。
df_temp = pd.DataFrame({"A": [1, 2, 3]}) df_temp.dtypes
A int64
dtype: object
例えば、上記と同じデータに対して、データ型int8
を指定してDataFrameを作ってみよう。
このDataFrameに対してinfer_objects()を実施すると、
「通常のSeries/DataFrameの作成をするとき」と同じ推測を実行するのだから、上記の結果と同じint64になると期待される。
df4 = pd.DataFrame({"A": [1, 2, 3]}, dtype='int8') df4.dtypes
A int8
dtype: object
# 上のdf_tempと同じ型になるのだろうか?
df4.infer_objects().dtypes
A int8
dtype: object
えっ。どういうことなの。今あるデータに対して、型の推測をいま一度実施して、特にint64が出力されるんじゃないの?
infer_objects() 何もわからない。
今日の結論
infer_objects() 何もわからない。