【はじめに】
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