上級マクロ経済学

第7回 データの加工

Author

荻巣嘉高

1 データの加工

データクリーニング

データの提供元から得られたデータは、たいていの場合、分析者にとって非常に雑多な体裁をしている。

  • 多数の謎空白と欠損値
  • 意味のない全角スペース
  • ラベル行の非統一性
  • アプリケーション依存の日付表示

このようなデータを分析しやすいように加工することを、データクリーニングという。

データクリーニングの注意点

データ元からDLしたデータを、直接加工することは基本的にNG

  • 基本は、Excel、csvなどをコードで加工する。
    • データに対してどのような操作を行なったか、履歴を全てコードに残す。
    • これが、分析の再現性と客観性を担保する。
    • 加工し終えたファイルを最後にExcelやcsvのファイルとして保存する。
  • それができない場合も、元データを直接加工するのではなく、別名で保存したファイルを編集する。
    • 元ファイルは基本いじらない!

Pythonでのデータクリーニング

Pythonでのデータクリーニングは基本、pandasのデータフレームを使って行えば良い。

  1. 加工前のデータを読み込む(例えば、df0)。
  2. 加工したデータを保存するDataFrameを別に作成する(例えば、df1)。
  3. df0のデータを条件一致で抜き出し、df1に追加していく。
  4. 終わったらdf1.to_excel()df1.to_csv()で保存する。

PWTデータ加工

  • 配布しているpwt1001.xlsxはPenn World TableからダウンロードしたExcelファイルです。
  • ここから次の二つを抜き出しましょう。
    • 日本の実質GDP(支出側)
    • 日本の被雇用者数

構造の確認

先にExcelで開いてみてどんな構造のファイルかを確認します。

  • infoタブにソースの情報が入っている。
  • Legendタブにそれぞれのラベルが何を意味するかの説明が入っている。
  • Dataタブにデータが入っている。

手順を考える

  • read_excel()で、sheet_name="Data"で読み込めば良さそう。
  • 実質GDP(支出側)のラベルはrgdpe(in mil. 2017US$)
  • 被雇用者数の数はemp(in mil.)
  • 日本のデータはcountryJapanとなっているはず

とわかる。

加工:読み込みとチェック&保存先の作成

import pandas as pd

df0 = pd.read_excel("./pwt1001.xlsx",sheet_name="Data")
df1 = pd.DataFrame()

df0 # チェック
countrycode country currency_unit year rgdpe rgdpo pop emp avh hc ... csh_x csh_m csh_r pl_c pl_i pl_g pl_x pl_m pl_n pl_k
0 ABW Aruba Aruban Guilder 1950 NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 ABW Aruba Aruban Guilder 1951 NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 ABW Aruba Aruban Guilder 1952 NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 ABW Aruba Aruban Guilder 1953 NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 ABW Aruba Aruban Guilder 1954 NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
12805 ZWE Zimbabwe US Dollar 2015 40141.617188 39798.644531 13.814629 6.393752 NaN 2.584653 ... 0.140172 -0.287693 -0.051930 0.479228 0.651287 0.541446 0.616689 0.533235 0.425715 1.778124
12806 ZWE Zimbabwe US Dollar 2016 41875.203125 40963.191406 14.030331 6.504374 NaN 2.616257 ... 0.131920 -0.251232 -0.016258 0.470640 0.651027 0.539631 0.619789 0.519718 0.419446 1.728804
12807 ZWE Zimbabwe US Dollar 2017 44672.175781 44316.742188 14.236595 6.611773 NaN 2.648248 ... 0.126722 -0.202827 -0.039897 0.473560 0.639560 0.519956 0.619739 0.552042 0.418681 1.756007
12808 ZWE Zimbabwe US Dollar 2018 44325.109375 43420.898438 14.438802 6.714952 NaN 2.680630 ... 0.144485 -0.263658 -0.020791 0.543757 0.655473 0.529867 0.641361 0.561526 0.426527 1.830088
12809 ZWE Zimbabwe US Dollar 2019 42296.062500 40826.570312 14.645468 6.831017 NaN 2.713408 ... 0.213562 -0.270959 -0.089798 0.494755 0.652439 0.500927 0.487763 0.430082 0.419883 1.580885

12810 rows × 52 columns

加工:Japanの抜き出し

df0 = pd.read_excel("./pwt1001.xlsx",sheet_name="Data")

df_jp = df0[df0["country"] == "Japan"] # countryがJapanであるような行を抜き出す。

df_jp
countrycode country currency_unit year rgdpe rgdpo pop emp avh hc ... csh_x csh_m csh_r pl_c pl_i pl_g pl_x pl_m pl_n pl_k
6090 JPN Japan Yen 1950 2.426405e+05 2.363832e+05 84.274267 39.407654 2030.413757 2.290001 ... 0.045103 -0.050710 0.022848 0.053976 0.079920 0.022293 0.088672 0.079598 0.052085 NaN
6091 JPN Japan Yen 1951 2.700028e+05 2.612887e+05 85.640724 40.384689 2012.990686 2.322519 ... 0.062006 -0.076433 0.027957 0.062285 0.086277 0.029007 0.112164 0.091341 0.058287 NaN
6092 JPN Japan Yen 1952 2.953554e+05 2.878446e+05 86.943150 41.342064 1995.717124 2.355500 ... 0.058143 -0.077189 0.024778 0.064871 0.094902 0.031018 0.102219 0.087548 0.064941 NaN
6093 JPN Japan Yen 1953 3.098569e+05 3.007139e+05 88.145992 42.261971 1978.591787 2.388948 ... 0.052907 -0.091141 0.024674 0.069607 0.099742 0.035257 0.105951 0.084528 0.067756 NaN
6094 JPN Japan Yen 1954 3.292969e+05 3.166364e+05 89.250869 42.801991 2008.945400 2.422872 ... 0.052276 -0.089065 0.024347 0.073461 0.096893 0.038168 0.111902 0.082793 0.065208 0.817996
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
6155 JPN Japan Yen 2015 5.094436e+06 5.154500e+06 127.985133 66.983032 1756.900000 3.550699 ... 0.176910 -0.164821 -0.004033 0.866159 0.864725 0.861740 0.687518 0.738765 0.848375 0.766573
6156 JPN Japan Yen 2016 4.982680e+06 5.042444e+06 127.763265 67.620995 1747.100000 3.561472 ... 0.187148 -0.163601 0.002189 1.022771 0.960890 0.955459 0.684445 0.736817 0.938162 0.812597
6157 JPN Japan Yen 2017 5.003368e+06 5.048890e+06 127.502725 68.253265 1743.700000 3.572278 ... 0.198780 -0.184377 0.003832 1.008958 0.946071 0.911619 0.695581 0.721318 0.961352 0.807656
6158 JPN Japan Yen 2018 4.983271e+06 5.005677e+06 127.202192 69.364609 1729.000000 3.583116 ... 0.200939 -0.198318 0.004355 1.031726 0.980421 0.922165 0.734720 0.754529 0.993066 0.780971
6159 JPN Japan Yen 2019 5.028348e+06 5.036891e+06 126.860301 69.976692 1691.085260 3.593987 ... 0.190841 -0.190701 0.005592 1.048585 1.007949 0.932528 0.734816 0.751225 1.011635 0.788685

70 rows × 52 columns

加工:GDPの抜き出し

#df_jp.loc["rgdpe"] # こっちでもOK
df_jp.loc[:,"rgdpe"].head() # チェック
6090    242640.53125
6091    270002.81250
6092    295355.43750
6093    309856.87500
6094    329296.90625
Name: rgdpe, dtype: float64

このうちのを、保存先に代入

df1["rgdpe"] = df_jp.loc[:,"rgdpe"].values # valuesを忘れず。
# valuesなしだと、「indexを合わせて新規列を作成する」ために、思わぬ挙動をする場合があります。

df1.head() #チェック
rgdpe
0 242640.53125
1 270002.81250
2 295355.43750
3 309856.87500
4 329296.90625

加工:被雇用者数の抜き出し

#df_jp.loc["enp"] # こっちでもOK
df_jp.loc[:,"emp"].head() # チェック
6090    39.407654
6091    40.384689
6092    41.342064
6093    42.261971
6094    42.801991
Name: emp, dtype: float64

このうちのを、保存先に代入

df1["emp"] = df_jp.loc[:,"emp"].values # valuesを忘れず。
# ここでもvaluesをつけるのが推奨。

df1.head() #チェック
rgdpe emp
0 242640.53125 39.407654
1 270002.81250 40.384689
2 295355.43750 41.342064
3 309856.87500 42.261971
4 329296.90625 42.801991

加工:インデックスの置き換え

インデックスを年にしたいので、置き換える。

df_jp["year"].head() # チェック
6090    1950
6091    1951
6092    1952
6093    1953
6094    1954
Name: year, dtype: int64

このうちのを、df1のインデックスに代入する。

df1.index = df_jp["year"].values

df1.head() # チェック
rgdpe emp
1950 242640.53125 39.407654
1951 270002.81250 40.384689
1952 295355.43750 41.342064
1953 309856.87500 42.261971
1954 329296.90625 42.801991

加工:データ保存

加工したデータを保存したら加工完了。

  • csvがおすすめ
df1.to_csv("./jpn_gdp_and_emp.csv") # 作業ディレクトリにcsv作成
df1.to_excel("./jpn_gdp_and_emp.xlsx") # 作業ディレクトリにexcel作成
  • できたファイルをExcelなどで開いてチェック。

まとめ

  • 神エクセルをはじめ、たくさんの謎フォーマットデータが溢れている。
  • チェックしながらの加工作業は大変だが、これができるようになることがデータ分析の第一歩。
  • Pandasの挙動は少しクセがあるように感じるかもしれない。こればかりは慣れるほかない。
    • 人によっては、データクリーニングは別のプログラミング言語で行い、分析はPython、みたいな人もいます。