CUBE SUGAR CONTAINER

技術系のこと書きます。

Python: pandas で数の少ない項目を「その他」にまとめる

pandas で集計した内容をグラフにするとき、数の少ない項目がたくさんあるとごちゃっとしてしまう。 今回は、そんな数の少ない項目を「その他」としてまとめる方法について。

使った環境は次の通り。

$ sw_vers 
ProductName:    Mac OS X
ProductVersion: 10.12.6
BuildVersion:   16G29
$ python --version
Python 3.6.3

下準備

まずは pandas をインストールしておく。

$ pip install pandas
$ pip list --format=columns | grep pandas
pandas          0.21.0 

サンプルとなるデータ

サンプルとしては各国の GDP を使うことにした。

以下は 2016 年の GDP 上位 10 ヶ国を示している。

>>> columns = ['country', 'gdp']
>>> data = [
...     ['ITA', 1849970464191],
...     ['CAN', 1529760492201],
...     ['JPN', 4939383909875],
...     ['IND', 2263522518124],
...     ['USA', 18569100000000],
...     ['BRA', 1796186586414],
...     ['CHN', 11199145157649],
...     ['GBR', 2618885692029],
...     ['FRA', 2465453975282],
...     ['DEU', 3466756880460],
... ]
>>> import pandas as pd
>>> df = pd.DataFrame(data, columns=columns)

このデータを使って、上位 5 ヶ国はそのままに下位 5 ヶ国を「その他」としてまとめてしまうことにする。

まずは、そのまま使う上位 5 ヶ国を取り出す。 これには gdp のカラムを使って値の大きいものを DataFrame#nlargest() メソッドで取り出す。

>>> df.nlargest(5, columns='gdp')
  country             gdp
4     USA  18569100000000
6     CHN  11199145157649
2     JPN   4939383909875
9     DEU   3466756880460
7     GBR   2618885692029
>>> df_largest = df.nlargest(5, columns='gdp')

ひとまず、これを df_largest という変数に格納しておく。

ちなみに別解としては DataFrame#sort_values() を使ってソートした上で先頭を取り出しても良い。

>>> df.sort_values('gdp', ascending=False)
  country             gdp
4     USA  18569100000000
6     CHN  11199145157649
2     JPN   4939383909875
9     DEU   3466756880460
7     GBR   2618885692029
8     FRA   2465453975282
3     IND   2263522518124
0     ITA   1849970464191
5     BRA   1796186586414
1     CAN   1529760492201
>>> df.sort_values('gdp', ascending=False)[:5]
  country             gdp
4     USA  18569100000000
6     CHN  11199145157649
2     JPN   4939383909875
9     DEU   3466756880460
7     GBR   2618885692029

続いては「その他」にまとめたい下位 5 ヶ国を取り出す。 これには DataFrame#drop() メソッドに、さきほど作った上位 5 ヶ国のデータフレームの index プロパティを渡せば良い。

>>> df.drop(df_largest.index)
  country            gdp
0     ITA  1849970464191
1     CAN  1529760492201
3     IND  2263522518124
5     BRA  1796186586414
8     FRA  2465453975282
>>> df_others = df.drop(df_largest.index)

この内容は df_others として格納しておく。

続いては「その他」にまとめたい内容を DataFrame#sum() メソッドで集約してしまう。

>>> df_others.sum()['gdp']
9904894036212

上記の内容を使って新しい DataFrame オブジェクトを作る。 カラムの内容は揃えた上で国名には Others を指定してやる。

>>> pd.DataFrame([['Others', df_others.sum()['gdp']]], columns=df.columns)
  country            gdp
0  Others  9904894036212
>>> df_others_sum = pd.DataFrame([['Others', df_others.sum()['gdp']]], columns=df.columns)

この内容を df_others_sum という変数に入れておく。

あとは、最初に作った上位 5 ヶ国の df_largest と下位 5 ヶ国を集約した df_others_sumconcat() 関数で連結するだけ。

>>> pd.concat([df_largest, df_others_sum], ignore_index=True)
  country             gdp
0     USA  18569100000000
1     CHN  11199145157649
2     JPN   4939383909875
3     DEU   3466756880460
4     GBR   2618885692029
5  Others   9904894036212

これで下位の内容を「その他」にまとめることができた。

めでたしめでたし。