2
6

More than 1 year has passed since last update.

【Pandas】データを集計する方法 | groupby/pivot_table

Posted at

【はじめに】

Pythonライブラリの「Pandas」の中で、データを集計する方法として「groupby」、「pivot_table」があります。

どちらを使った方が良いのか分からない方のために、集計の目的に応じてどちらを使用するべきか分かりやすく紹介していきます。

本記事の内容

  • pandasのインポート
  • csvファイルの読み込み
  • データを集計する | groupby
  • データを集計する | pivot_table

【pandasのインポート】

import pandas as pd

【csvファイルの読み込み】

「1920年から2015年までの全国の人口推移のデータ」を使用します。

df = pd.read_csv('data.csv', encoding='shift-jis')
df
都道府県コード 都道府県名 元号 和暦(年) 西暦(年) 人口(総数) 人口(男) 人口(女)
0 1 北海道 大正 9 1920 2359183 1244322 1114861
1 2 青森県 大正 9 1920 756454 381293 375161
2 3 岩手県 大正 9 1920 845540 421069 424471
3 4 宮城県 大正 9 1920 961768 485309 476459
4 5 秋田県 大正 9 1920 898537 453682 444855
... ... ... ... ... ... ... ... ...
934 43 熊本県 平成 27 2015 1786170 841046 945124
935 44 大分県 平成 27 2015 1166338 551932 614406
936 45 宮崎県 平成 27 2015 1104069 519242 584827
937 46 鹿児島県 平成 27 2015 1648177 773061 875116
938 47 沖縄県 平成 27 2015 1433566 704619 728947
939 rows × 8 columns

私のGitHubに「data.csv」としてアップロードしてあるので、下記コマンドでダウンロードすれば簡単に準備できます。

$ curl https://raw.githubusercontent.com/nakachan-ing/python-references/master/Pandas/data.csv -O

【データを集計する | groupby】

groupbyメソッドを使用すると、DataFrameの要素をもとにデータをグループ分けして、簡単に集計することができます。

引数byにグループ分けしたカラムを指定します。

読み込んだcsvファイルから「都道府県別」に、「人口(総数)」、「人口(男)」、「人口(女)」それぞれを集計してみます。

df_mean1 = df.groupby(by='都道府県名').mean()[['人口(総数)', '人口(男)', '人口(女)']]
df_mean1.head(10)
人口(総数) 人口(男) 人口(女)
都道府県名
三重県 1534021.4 743366.55 790654.85
京都府 2135317.95 1044093.7 1091224.25
佐賀県 830574.25 395550.75 435023.5
兵庫県 4233525 2067583.1 2165941.9
北海道 4606104.3 2272235.25 2333869.05
千葉県 3591668.1 1789946.8 1801721.3
和歌山県 978371.25 471085.7 507285.55
埼玉県 4040109.05 2023428.05 2016681
大分県 1142165.05 544737.95 597427.1
大阪府 6380772.25 3167758.65 3213013.6

ポイント

  • DataFrameに対して、はじめに「都道府県名」でグループ分けしてから、「人口(総数)」、「人口(男)」、「人口(女)」の平均を抽出しています。
  • DataFrameに対して、はじめに「都道府県名」、「人口(総数)」、「人口(男)」、「人口(女)」のデータを抽出してから「都道府県名」でグループ分けして平均を求めることもできます。
df_mean2 = df[['都道府県名', '人口(総数)', '人口(男)', '人口(女)']].groupby(by='都道府県名').mean()
df_mean2.head(10)
人口(総数) 人口(男) 人口(女)
都道府県名
三重県 1534021.4 743366.55 790654.85
京都府 2135317.95 1044093.7 1091224.25
佐賀県 830574.25 395550.75 435023.5
兵庫県 4233525 2067583.1 2165941.9
北海道 4606104.3 2272235.25 2333869.05
千葉県 3591668.1 1789946.8 1801721.3
和歌山県 978371.25 471085.7 507285.55
埼玉県 4040109.05 2023428.05 2016681
大分県 1142165.05 544737.95 597427.1
大阪府 6380772.25 3167758.65 3213013.6

groupbyメソッドで集計できるものとしては、

  • mean(平均)
  • sum(合計)
  • count(個数)
  • max(最大値)
  • min(最小値)
  • std(標準偏差)
  • var(分散)

などがあります。

複数要素でグルーピングする

groupbyメソッドの引数byにリストで複数のカラムを指定することで、複数要素での集計が可能です。

「都道府県名」と「元号」をリスト形式で指定して、「人口(総数)」、「人口(男)」、「人口(女)」それぞれの平均を集計してみます。

df_mean3 = df[['都道府県名', '元号', '人口(総数)', '人口(男)', '人口(女)']].groupby(by=['都道府県名', '元号']).mean()
df_mean3
人口(総数) 人口(男) 人口(女)
都道府県名 元号
三重県 大正 1.09E+06 5.35E+05 5.53E+05
平成 1.84E+06 8.93E+05 9.45E+05
昭和 1.46E+06 7.03E+05 7.53E+05
京都府 大正 1.35E+06 6.84E+05 6.63E+05
平成 2.63E+06 1.27E+06 1.36E+06
... ... ... ... ...
鳥取県 平成 6.02E+05 2.88E+05 3.14E+05
昭和 5.66E+05 2.71E+05 2.95E+05
鹿児島県 大正 1.44E+06 6.98E+05 7.46E+05
平成 1.75E+06 8.19E+05 9.29E+05
昭和 1.75E+06 8.30E+05 9.20E+05
141 rows × 3 columns

このままだと人口が指数表示となってしまい、ひと目では何人なのか分かりにくいですね。

※指数表現は数値を1桁にして、その分10を何乗したかで表現しています。

ひと目で人口が分かるように、round(0)とすることで、小数点以下を切り捨てて表現します。

df_mean3.round(0)
人口(総数) 人口(男) 人口(女)
都道府県名 元号
三重県 大正 1088481.0 535354.0 553126.0
平成 1838127.0 893168.0 944960.0
昭和 1456225.0 703135.0 753090.0
京都府 大正 1346764.0 684122.0 662642.0
平成 2628425.0 1268325.0 1360099.0
... ... ... ... ...
鳥取県 平成 602177.0 287885.0 314291.0
昭和 565924.0 270756.0 295169.0
鹿児島県 大正 1443888.0 697972.0 745915.0
平成 1747640.0 818506.0 929134.0
昭和 1749826.0 829889.0 919936.0
141 rows × 3 columns

aggメソッドを使って集計する

aggメソッドは平均や合計などを同時に集計することができます。

集計したい計算方法をaggメソッドの引数にリストで指定します。

「都道府県名」と「元号」をリスト形式で指定して、「人口(総数)」、「人口(男)」、「人口(女)」それぞれの平均、最大値、最小値を集計してみます。

df_culc1 = df[['都道府県名', '元号', '人口(総数)', '人口(男)', '人口(女)']].groupby(by=['都道府県名', '元号']).agg(['mean', 'max', 'min'])
df_culc1.round(0)
人口(総数) 人口(男) 人口(女)
mean max min mean max min mean max min
都道府県名 元号
三重県 大正 1088481.0 1107692.0 1069270.0 535354 544752 525957 553126 562940 543313
平成 1838127 1866963.0 1792514.0 893168.0 907214 869515 944960 959749 922999
昭和 1456225 1747311.0 1157407.0 703135.0 847420 571000 753090 899891 586407
京都府 大正 1346764.0 1406382.0 1287147.0 684122 717464 650780 662642 688918 636367
平成 2628425 2647660 2602460 1268325 1278142 1248972 1360099 1374667 1334840
... ... ... ... ... ... ... ... ... ... ...
鳥取県 平成 602177.0 615722.0 573441.0 287885 294899 273705 314291 320823 299736
昭和 565924 616024.0 484390.0 270756.0 297015 233964 295169 320513 250182
鹿児島県 大正 1443888.0 1472193.0 1415582.0 697972 713702 682243 745915 758491 733339
平成 1747640 1797824.0 1648177.0 818506.0 842474 773061 929134 955350 875116
昭和 1749826 2044112 1538466 829889 985617 699455 919936 1058495 803046
141 rows × 9 columns

ポイント

統計量を算出したい場合は、aggメソッドの引数にdescribeを指定します。

「都道府県名」と「元号」をリスト形式で指定して、「人口(総数)」の平均、最大値、最小値を集計してみます。

df_culc2 = df[['都道府県名', '元号', '人口(総数)']].groupby(by=['都道府県名', '元号']).agg('describe')
df_culc2.round(0)
人口(総数)
count mean std min 25% 50% 75% max
都道府県名 元号
三重県 大正 2.0 1088481.0 27168.0 1069270 1078876 1088481 1098086 1107692
平成 6 1838127 28505.0 1792514.0 1822238.0 1848041 1856685 1866963
昭和 12 1456225 194973.0 1157407.0 1345410.0 1485318 1563813 1747311
京都府 大正 2.0 1346764.0 84312.0 1287147 1316956 1346764 1376573 1406382
平成 6 2628425 18362 2602460 2615163 2632842 2642316 2647660
... ... ... ... ... ... ... ... ... ...
鳥取県 平成 6.0 602177.0 17328.0 573441 593253 610150 614519 615722
昭和 12 565924 49776.0 484390.0 545030.0 580582 601188 616024
鹿児島県 大正 2.0 1443888.0 40030.0 1415582 1429735 1443888 1458040 1472193
平成 6 1747640 59686.0 1648177.0 1717976.0 1769686 1792216 1797824
昭和 12 1749826 161160 1538466 1590966 1756886 1827838 2044112
141 rows × 8 columns

小数点以下を切り捨てたことで見やすくなっていますが、桁区切り表示させることでより分かりやすくできます。

applymapメソッドとformatメソッドを使って3桁区切りにします。

df_culc2.applymap('{:,.0f}'.format)
人口(総数)
count mean std min 25% 50% 75% max
都道府県名 元号
三重県 大正 2 1,088,481 27,168 1,069,270 1,078,876 1,088,481 1,098,086 1,107,692
平成 6 1,838,127 28,505 1,792,514 1,822,238 1,848,041 1,856,685 1,866,963
昭和 12 1,456,225 194,973 1,157,407 1,345,410 1,485,318 1,563,813 1,747,311
京都府 大正 2 1,346,764 84,312 1,287,147 1,316,956 1,346,764 1,376,573 1,406,382
平成 6 2,628,425 18,362 2,602,460 2,615,163 2,632,842 2,642,316 2,647,660
... ... ... ... ... ... ... ... ... ...
鳥取県 平成 6 602,177 17,328 573,441 593,253 610,150 614,519 615,722
昭和 12 565,924 49,776 484,390 545,030 580,582 601,188 616,024
鹿児島県 大正 2 1,443,888 40,030 1,415,582 1,429,735 1,443,888 1,458,040 1,472,193
平成 6 1,747,640 59,686 1,648,177 1,717,976 1,769,686 1,792,216 1,797,824
昭和 12 1,749,826 161,160 1,538,466 1,590,966 1,756,886 1,827,838 2,044,112
141 rows × 8 columns

【データを集計する | pivot_table】

groupbyメソッドではカラム(縦方向)でグルーピングして集計をしましたが、pivot_tableメソッドでは横方向にも項目を追加して集計することができます。

引数indexには縦方向に表示させたい項目、columnsには横方向に表示させたい項目を指定します。

引数valuesに集計するデータのカラムを指定します。

引数aggfuncには集計方法を指定します。

indexに「都道府県名」、columnsに「元号」を指定して、「人口(総数)」の平均を集計してみます。

df_pivot1 = df.pivot_table(index='都道府県名', columns='元号', values='人口(総数)', aggfunc='mean')
df_pivot1.round(0).head(10)
元号 大正 平成 昭和
都道府県名
三重県 1088481 1838127.0 1456225.0
京都府 1346764 2,628,425 2,020,190
佐賀県 679363 864,635 838,746
兵庫県 2378239 5,511,838 3,903,583
北海道 2428931 5,589,153 4,477,442
千葉県 1367706 5,962,486 2,776,920
和歌山県 768961 1037736.0 983590.0
埼玉県 1356997 6,936,328 3,039,185
大分県 887709 1,210,304 1,150,505
大阪府 2823674 8,809,791 5,759,113

複数のデータを集計する

複数データを同時に集計することができます。

indexに「都道府県名」、columnsに「元号」を指定して、「人口(総数)」、「人口(男)」、「人口(女)」人口の平均を集計してみます。

df_pivot2 = df.pivot_table(index='都道府県名', columns='元号', values=['人口(総数)', '人口(男)', '人口(女)'], aggfunc='mean')
df_pivot2.round(0).head(10)
人口(女) 人口(男) 人口(総数)
元号 大正 平成 昭和 大正 平成 昭和 大正 平成 昭和
都道府県名
三重県 553126 944,960 753,090 535,354 893,168 703,135 1,088,481 1,838,127 1,456,225
京都府 662642 1,360,099 1,028,217 684,122 1,268,325 991,973 1,346,764 2,628,425 2,020,190
佐賀県 346270 456,442 439,106 333,092 408,192 399,640 679,363 864,635 838,746
兵庫県 1170863 2,861,527 1,983,996 1,207,376 2,650,310 1,919,587 2,378,239 5,511,838 3,903,583
北海道 1154034 2,923,372 2,235,757 1,274,898 2,665,781 2,241,685 2,428,931 5,589,153 4,477,442
千葉県 693601 2974638.0 1399949.0 674105.0 2987847 1376970 1367706 5962486 2776920
和歌山県 386836 547,112 507,447 382,124 490,624 476,143 768,961 1,037,736 983,590
埼玉県 695390 3,443,448 1,523,513 661,606 3,492,880 1,515,672 1,356,997 6,936,328 3,039,185
大分県 450706 638,774 601,207 437,003 571,531 549,297 887,709 1,210,304 1,150,505
大阪府 1354138 4,517,115 2,870,776 1,469,536 4,292,676 2,888,337 2,823,674 8,809,791 5,759,113

複数の集計方法を同時に実行する

引数aggfuncにリストで集計方法を指定することで、複数の集計方法を同時に実行することができます。

indexに「都道府県名」、columnsに「元号」を指定して、「人口(総数)」の平均、最大値、最小値を集計してみます。

df_pivot3 = df.pivot_table(index='都道府県名', columns='元号', values='人口(総数)', aggfunc=['mean', 'max', 'min'])
df_pivot3.round(0).head(10)
mean max min
元号 大正 平成 昭和 大正 平成 昭和 大正 平成 昭和
都道府県名
三重県 1088481 1,838,127 1,456,225 1,107,692 1,866,963 1,747,311 1,069,270 1,792,514 1,157,407
京都府 1346764 2,628,425 2,020,190 1,406,382 2,647,660 2,586,574 1,287,147 2,602,460 1,552,832
佐賀県 679363 864,635 838,746 684,831 884,316 973,749 673,895 832,832 686,117
兵庫県 2378239 5,511,838 3,903,583 2,454,679 5,590,601 5,278,050 2,301,799 5,401,877 2,646,301
北海道 2428931 5,589,153 4,477,442 2,498,679 5,692,321 5,679,439 2,359,183 5,381,733 2,812,335
千葉県 1367706 5962486.0 2776920.0 1399257.0 6222666 5148163 1336155 5555429 1470121
和歌山県 768961 1,037,736 983,590 787,511 1,080,435 1,087,206 750,411 963,579 830,748
埼玉県 1356997 6,936,328 3,039,185 1,394,461 7,266,534 5,863,678 1,319,533 6,405,319 1,459,172
大分県 887709 1,210,304 1,150,505 915,136 1,236,942 1,277,199 860,282 1,166,338 945,771
大阪府 2823674 8,809,791 5,759,113 3,059,502 8,865,245 8,668,095 2,587,847 8,734,516 2,800,958

【さいごに】

今回はデータを集計する方法として「groupby」、「pivot_table」を紹介しました。

特に「pivot_table」はシンプルかつ非常に分かりやすいデータ分析手法です。

これを機に覚えてしまいましょう。

使用したCSVファイルやJupyter NotebookはGitHubに公開しています。
Jupyter Notebookは下記コマンドでダウンロードできるので、自由に使って是非練習してみてください。

$ curl https://raw.githubusercontent.com/nakachan-ing/python-references/master/Pandas/pandasでデータ集計する.ipynb -O

2
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
6