koji/メガネ男の日誌

日々の学び、活動状況を記録します。仕事のことは少なめ。

PandasのGroupby集計でつまづいたのでまとめてみた

PandasのGroupby集計でつまづいたのでまとめてみました。

なお、データはKaggleのTitanic train.csvを使っています www.kaggle.com

環境 Windows10、Anaconda ver1.97、python 3.69、jupyter notebook

詰まったのは、groupby()のas_index=Falseの指定です。

まずtrain.csvをKaggleのサイトからダウンロードして読み込みます。

import pandas as pd
data1 = pd.read_csv("C:xxxxxxx/train.csv")
data1

xxxxx の部分はtrain.csvを入れたパスです。 pwdや、import os のちのos.cwd()で確認ください。

f:id:kj_man666:20200118180737p:plain

年齢('Age')でグルーピング化して、料金('Fare')を集計、料金('Fare')の降順に並び替え、 料金('Fare')を4分割してグループ名を付けて、4つのグループごとに集計し、構成割合を付けます。

NaN値があるとややこしいので、isnull()で確かめます。 年齢('Age')に177個のNaN値があることがわかります。

data1.isnull().sum()

f:id:kj_man666:20200118180952p:plain

今回は予測が目的ではないので、NaN値はばっさり削除します。 また、客室('Cabin')や出航地('Embarked')は今回使わないので無視します。

data1_Age_nonNull = data1.dropna(subset=["Age"])

再びNaN値を数えると、ちゃんと年齢('Age')のNaN値はゼロになっていますね。

data1_Age_nonNull.isnull().sum()

f:id:kj_man666:20200118181139p:plain

年齢('Age')をベースに、料金('Fare')で集計すると88項目に集約されます。 なお、引っかかったのはこちらでして、先に間違いだったコードを記載します。

data2

f:id:kj_man666:20200118181252p:plain

このままグループ名を適当に付けて、data2に新しくグループ列を作り、qcut()関数で4分割して グループ名をグループ列に入れると、エラーが発生します。

なお、qcut()は「数」をベースに指定の分割を行うことができる関数です。 pandasのcut, qcut関数でビニング処理(ビン分割) | note.nkmk.me

group_names = ['1st','2nd','3rd','4th']
data2['Group'] = pd.qcut(data2['Fare'], 4, labels=group_names)
data2

KeyError: 'Fare'

調べたところ、これは、Groupby()の中に、as_index=False を入れなかったため、 データが1次元構造のSeries型になってしまい、列名 料金('Fare')が消えてしまったことが要因のようです。

細かいことは下記の記事をお読みください。

qiita.com

qiita.com

正しいコードは下記のとおりです。

data2 = data1_Age_nonNull.groupby(['Age'], as_index=False)['Fare'].sum().sort_values(by=['Fare'], ascending=False)
data2

f:id:kj_man666:20200118181900p:plain

(参考) 誤ったコードのdata2の型

data2.dtypes

dtype('float64')

正しいコードのdata2の型

data3.dtypes

Group category Fare float64 dtype: object

groupby()の処理をする際、

.groupby(['Age'], as_index=False)

とすることで、二次元構造のDataFrame型を維持することができ、列名 料金('Fare')で集計することが可能となります。 Series型にしてしまうと、列名 料金('Fare')が消えてしまうのです。

正しいコードで記載した後は、

group_names = ['1st','2nd','3rd','4th']
data2['Group'] = pd.qcut(data2['Fare'], 4, labels=group_names)
data2

f:id:kj_man666:20200118182409p:plain

data3 = data2.groupby(['Group'], as_index=False)['Fare'].sum().sort_values(by=['Fare'], ascending=True)
data3

f:id:kj_man666:20200118182332p:plain

data3['SalesRatio'] = data3['Fare'] / data3['Fare'].sum()
data3

f:id:kj_man666:20200118182240p:plain

以上になります、最後までお読みいただきありがとうございました。