なんか pandas の groupby の計算がうまく動かないので、同じように困っている人(がもしいたら、、)のための情報です。
うまくいく使い方
pandasでは、groupbyでグループ分けして、平均とかを計算できます。
import pandas as pd
df = pd.DataFrame({
'city' : ['tokyo', 'tokyo', 'osaka', 'osaka'],
'month': ['April', 'May', 'April','May'],
'price': [200, 300, 150, 250]
})
print(df.groupby('city').mean())
出力
price
city
osaka 200.0
tokyo 250.0
うまく行かない場合
ところが、空の DataFrame を最初に作っておいて、行を追加して実行すると、うまく動きません。
df0 = pd.DataFrame(columns=['city','month','price'])
df0 = df0.append({'city':'tokyo', 'month':'April', 'price':200}, ignore_index=True)
df0 = df0.append({'city':'tokyo', 'month':'May', 'price':300}, ignore_index=True)
df0 = df0.append({'city':'osaka', 'month':'April', 'price':150}, ignore_index=True)
df0 = df0.append({'city':'osaka', 'month':'May', 'price':250}, ignore_index=True)
print(df0.groupby('city').mean())
結果
Empty DataFrame
Columns: []
Index: [osaka, tokyo]
dfとdf0は、print しただけでは全く同じ。
print(df)
print(df0)
print(type(df))
print(type(df0))
出力
city month price
0 tokyo April 200
1 tokyo May 300
2 osaka April 150
3 osaka May 250
city month price
0 tokyo April 200
1 tokyo May 300
2 osaka April 150
3 osaka May 250
<class 'pandas.core.frame.DataFrame'>
<class 'pandas.core.frame.DataFrame'>
(あれ?良く見ると、空白1個分ずれているけど、これが何か悪さしているのかな?)
少し変えると動く
ちなみに、空の DataFrame の作り方によっては、うまくいく場合もある。
df0 = pd.DataFrame({'city':[], 'month':[], 'price':[]})
df0 = df0.append({'city':'tokyo', 'month':'April', 'price':200}, ignore_index=True)
df0 = df0.append({'city':'tokyo', 'month':'May', 'price':300}, ignore_index=True)
df0 = df0.append({'city':'osaka', 'month':'April', 'price':150}, ignore_index=True)
df0 = df0.append({'city':'osaka', 'month':'May', 'price':250}, ignore_index=True)
print(df0.groupby('city').mean())
出力
price
city
osaka 200.0
tokyo 250.0
感想
pandasの公式マニュアルを見ても、empty DataFrame の作り方は見つからないので、そもそもこういう使い方が良くない使い方のような感じです。
解決
公式サイトを良く見たら、
https://pandas.pydata.org/docs/user_guide/groupby.html?highlight=empty#other-useful-features
「以下のように書け」と書いてありました。これなら動きます。
df0.groupby(['city']).agg({'price': 'mean'})
何故こうなるかというと、price の型が異なっていて、
>>> df.dtypes
city object
month object
price int64
dtype: object
>>> df0.dtypes
city object
month object
price object
dtype: object
dfはすべてint64だと分かっているので、mean( ) の計算ができるけど、df0 は何が来るか分からないので mean( ) の計算は出来ないと認識されるため。agg を使うと、「そんなの良いから計算してよ」ということで計算してくれる。
(というのが私の理解)
ちなみに、「少し変えると動く」の方法だと、price は float だと推測される。型の推定のアルゴリズムが違うっぽい。
以上