Pythonと本と子供と雑談と

いつからはじめても遅くない

データ分析ハンズオンをやった

2月19日のはんなりPythonで久しぶりにハンズオンを行いました。

内容は家計調査の支出のcsvを取得、前処理、可視化、機械学習クラスタリング)というものでした。statsmodelsを利用して季節調整という内容も一応作っていたのですが、時間が足らずにできませんでした。残念。

やることと利用パッケージの関係は次の通り。

  • データの取得 Requests / pandas
  • 前処理 pandas
  • 可視化 Plotly / Dash
  • 機械学習 sklearn
  • 季節調整 statsmodels

リポジトリとコラボはリンク先にあります。

github.com

colab.research.google.com

忘れないうちにちょっとした解説を残しておきます。

その前に

このようなハンズオンで私がオープンデータを好んで使うのは次のような理由です。

  • ある程度手を加えると使える
  • ex.html#time)を取得、前処理、可視化、機械学習クラスタリング)というものでした。statsmodelsを利用して季節調整という内容も一応作っていたのですが、時間が足らずにできませんでした。残念。

やることと利用パッケージの関係は次の通り。

  • データの取得 Requests / pandas
  • 前処理 pandas
  • 可視化 Plotly / Dash
  • 機械学習 sklearn
  • 季節調整 statsmodels

リポジトリとコラボはリンク先にあります。

github.com

colab.research.google.com

忘れないうちにちょっとした解説を残しておくので、興味を持っていただいた方にはコラボを見ながらこれを読んでいただければと思います。

その前に

このようなハンズオンで私がオープンデータを好んで使うのは次のような理由です。

  • ある程度手を加えると使える
  • ある程度の人が興味を持てるデータ
  • 実際に仕事でも使えそう

データの取得

家計調査のcsvファイルは以前記事を書かせていただいたWEB+DB PRESS VOL118でも扱わせていただきました。でもその時はローカルに落としてからスタートみたいにしていました。その理由は・・・    

というのも、wgetやpandasのread_csv関数を用いて読み込むと、下のように何にもないという風になってしまうからでした。ちなみにyour-urlは取りたいデータのあるURLのことです。

!wget your-url

Image from Gyazo

他の方法で読み込むことはできるのだけれど、読み込んでほしそうにないデータを頑張って読み込むというのはあまり好まれそうもないので、ダウンロードしてからスタートにしました。

でも今回のハンズオンでは、ほかの方法で読み込むことにしました。この際用いるパッケージがRequestsでした。Requestsはウェブサイトをスクレイピングするときなどに用いるのですが、URLにある内容を読み込んでくれるのでファイルを読み込む際にも用いれます。そうしてエンコーディングを安定の"shift-jis"に変更します。

次に、読み込んだ文字列をファイルのように扱えるioモジュールのStringIOクラスを用いて読み込んだ文字列をread_csvを使って読み込むと、あら不思議!!さっきは見えなかったデータが読み込めていました。

from io import StringIO
import requests 
import pandas as pd 

r = requests.get(your-url)
r.encoding = 'shift-jis'
df = pd.read_csv(StringIO(r.text), encoding='shift-jis')

Image from Gyazo

はい。データの読み込みは以上のような感じです。実際にデータを集める場合は、もっと複雑になりがちなんですが、ハンズオンなんでちょっと工夫はいるが、その解決策が簡単であるというのはうれしいですね。

前処理

この事例での前処理は、次のようなことをおこないます。

  • バラバラになっている日付を作る
  • 必要なデータを抽出する

まずは日付ですが、pandasのdate_rangeを用いて作成します。データ自体が2000年1月から始まっているので、それは自分で指定し、その数は月のデータを用い、頻度の月は引数freqに'M'を渡すことで定義できます。

pd.date_range('2000-01-01', periods=len(tsuki[6:].values), freq='M')

そして作った日付をカラムに付け、必要なデータ(今回は商品のデータ)をスライスします。

可視化

可視化はplotly.expressを使って各商品を見る事例と、Dashを使ってよりインタラクティブに見る事例を作ってみました。

plotly.expressを用いると次のようにデータフレームを渡したあと、利用するカラム名を指定することにより、簡単にグラフを作ることができます。

import plotly.express as px

px.line(df2, x=df2.index, y=['米', 'パン'])

Image from Gyazo

こうしてyに入れる文字列を更新しながら、シフトエンターを連打するというのがこれまでのスタイルでしたが、今回使うような多くの要素を持つデータだと次のような問題があります。

  • 要素を全て網羅しにくい
  • それゆえデータの確認が漏れがち

そんな場合、Dashを使うとちょっとコードは増えますが、その分簡単にデータを確認できるようになります。Dashはウェブフレームワークなのですが、今回はjupyter上で使えるjupyter-dashを用いて実額と指数(2000年1月を100)、そして各商品を切り替えるアプリケーションを作成しました。

from jupyter_dash import JupyterDash 
import dash_html_components as html 
import dash_core_components as dcc 
from dash.dependencies import Input, Output

app = JupyterDash()

app.layout = html.Div([
                       dcc.Dropdown(id='sel_df', options=[{'value': d, 'label': d} for d in ['実額', '指数']], value='実額'),
                       dcc.Dropdown(id='ddown', options=[{'value': col, 'label': col} for col in df1.columns], value=['消費支出'], multi=True),
                       dcc.Graph(id='graph')
])
@app.callback(Output('graph', 'figure'), Input('sel_df', 'value'), Input('ddown', 'value'))
def update_graph(selected_df, selected_values):
  if selected_df == '実額':
    return px.line(df1, x=df1.index, y=selected_values)
  else:
    return px.line(df2, x=df2.index, y=selected_values)

app.run_server(mode='inline')

これで隅々まで消費支出のデータが見れます。

クラスタリング

調査を集計したデータに関して、時系列分析くらいしかやることないなってのがあるのですが、クラスタリングは役立つのでは?ということになり「確かに」という感じで、前のチュートリアルでなったので、今回もクラスタリングしてみました。指数化したデータを使ってクラスタリングしました(可視化したデータをトランスポーズしてひっくり返して)。

from sklearn.cluster import KMeans

df2_k = df2.T
model = KMeans(n_clusters=4, random_state=0)
cluster = model.fit_predict(df2_k)

クラスタの中央値?(平均値)はcluster_center_属性を使うと見れます。

cluster_df = pd.DataFrame(model.cluster_centers_)
cluster_df.columns = df2_k.columns 
cluster_df = cluster_df.T
px.line(cluster_df, x=cluster_df.index, y=[0,1,2,3])

Image from Gyazo

データを確認すると、めちゃ増えたもの、まぁまぁ増えた、横ばい、減ったという感じの4つに分類されていることが分かります。

まとめ

季節調整は会で扱えなかったので、また今度という感じにしたいと思います。

Pythonを使うと、以上のような感じで簡単にデータを取得、可視化、機械学習ができます。

会ではまとめの部分を話せなかったのですが、やってみるとデータを取ったり前処理の部分が意外と大変だなぁということを体感してもらえたかと思います。今回はしっかりと国が作っているデータなのである程度簡単ですが、これが手でエクセルを使って作られたデータだととんでもないことになるということは簡単に想像していただけるかと思います。

あと、コードをまとめて再利用できるようにしておくっての重要だと思います。

jupyter書きなぐりで終わるのはあまり良いことではありません。その辺りはおススメがあって、これまたWEB+DB PRESSのVOL118号の「現場のPython データ分析プログラムの改善方法」を読むのが良いと思いました。そういや、その号には私が書いた「Python可視化入門」が掲載されているようですよ。

plotly/Dashに関心を持っていただいた際には、Pythonインタラクティブデータビジュアライゼーション入門を買っていただければと思います。

あと、家計調査のデータを使って、野口先生が「コロナ「10万円給付」は空前のバラマキだった」という記事を書かれていました。実際に活用されている例として参照ください。

diamond.jp