エラー発生の経緯
KaggleのHomeCreditRiskのEDA(https://www.kaggle.com/code/osciiart/homecreditrisk-extensive-eda-baseline-model-jp/notebook)をKaggle Notebookと手元環境の両方で実行しました。
すると、手元環境でのみ以下のコードがTypeErrorを出しました。
prev_apps_avg = previous_application.groupby('SK_ID_CURR').mean()
TypeError: dtype 'str' does not support operation 'mean'
以下では調査の過程をまとめています。急ぎの方は「解決方法」へどうぞ。
原因の候補
エラーメッセージから、文字列カラムに対してmeanが実行されていることが原因だと推測できます。
まず、Kaggleと手元環境のバージョンを比較しました。ライブラリのメジャーバージョン差による挙動の違いが疑われます。
| 項目 | Kaggle | 手元の環境 |
| Python | 3.6.5 | 3.13.0 |
| pandas | 0.23.0 | 3.0.1 |
試したこと
pandas はデータ分析で広く使われているため、今回の調査は今後のトラブルシューティングにも役立つと考えています。
まずは、meanの挙動を確認するためにシンプルなコードを実行しました。
import sys
import pandas as pd
print(sys.version)
print(pd.__version__)
df = pd.DataFrame({
'A': [1, 2, 3, 1, 2, 3],
'B': ['a', 'b', 'c', 'd', 'e', 'f'],
'C': [10, 20, 30, 40, 50, 60]
})
print(df.groupby('A').mean())
C
A
1 25
2 35
3 45
出力を見ると、文字列カラムBが自動的に除外されて平均が計算されています。
そのため、バージョン差を吸収する暫定対策としては、事前に文字列カラムを削除する方法が考えられます。
df = df.drop(['B'], axis=1)
原因をより正確に把握するため、pandasのバージョンごとに挙動を比較しました。
pip index versions pandas
メジャーバージョン0~3が存在することを確認し、仮想環境でv1.5.3とv2.0.0を用意して検証しました。
python -m venv v_pd_v2
pip install pandas==2.0.0
結果は以下の通りです。
- v1.5.3→正常終了
- v2.0.0→TypeError発生
両バージョンのAPIリファレンスを確認すると、numeric_onlyのデフォルト値が変更されていました。
| 引数 | v1.5.3(v1.5.2)のデフォルト引数 | v2.0.0(v2.0.3)のデフォルト引数 |
| numeric_only | None(挙動は実質 True) | False |
| engine | “cython” | “cython” |
| engine_kwargs | None | None |
v2.0.0のwhat’s newにも以下の記述があります。
Changed default of numeric_only in various DataFrameGroupBy methods; all methods now default to numeric_only=False (GH 46072)
GitHubのissueをざっくりまとめると、
- v1までの非数値カラムの暗黙的なドロップについて問題視された
- v2からはnumeric_only=Trueを明示した場合のみ非数値カラムを除外する
という方針に変更されています。
v0系・v1系で書かれたコードをv2以降で動かす場合、以下のようにnumeric_only=Trueを明示する必要があります。
import sys
import pandas as pd
print(sys.version)
print(pd.__version__)
df = pd.DataFrame({
'A': [1, 2, 3, 1, 2, 3],
'B': ['a', 'b', 'c', 'd', 'e', 'f'],
'C': [10, 20, 30, 40, 50, 60]
})
# v1まで
# print(df.groupby('A').mean())
# v2以降
print(df.groupby('A').mean(numeric_only=True))
C
A
1 25
2 35
3 45
解決策
文字列を含むDataFrameの平均処理はpandasのバージョンで挙動が異なるため、以下のように書き分ける必要があります。
# v2.0.0より前(numeric_only=None だが非数値カラムは自動除外されるため実質 True)
df.groupby('A').mean()
# v2.0.0以降(numeric_only=Falseがデフォルト)
df.groupby('A').mean(numeric_only=True)
おわりに
最近は Copilot などの LLM に質問すれば多くの問題はすぐ解決できますが、今回は回答が得られなかったため、自分でリリースノートや Issue を読みながら調査しました。
結果として、ライブラリの仕様変更を追いかける良い練習になりました。

コメント