POSデータを用いた分析 -簡単な図示まで-

今回はインターネット環境さえあれば誰でも簡単にプログラミング言語Python(パイソン)を用いて解析を行うことができるGoogle Colaboratory(コラボラトリー)を利用した解析例を示す。(使用にはGoogleアカウントでのログインが必要だが、名城生はメイネットIDを用いたシングルサインオンで利用できる)

今回の実習では実際のID-POS(購買履歴)データを元に作成したデータを用いる。対象品目はコーヒーとして、スーパーマーケットで購買されたものである。

今回はデータの分析しやすさを高める目的でサンプルを大幅に絞っており、ある程度頻繁に購入している消費者のみを対象とした。

1 Colaboratoryにアクセスする

まずはColaboratoryにアクセスする。

右上からGoogleアカウントでログインしたら、左上[ファイル]から「Python 3の新しいノートブック」を選択して空のプロジェクトを作成する。

Colaboratoryではセルと呼ばれるブロックごとにプログラムを実行し結果を確認することができるようになっている(以下の画像はダークモードの画面になっているが、得られる結果など動作は一般のものと同様)。

たとえばRを使った経験のある人なら使用感は似ている。試しに2+3と入力して実行(左側の再生ボタンを押すかShift+Enter)すると…

結果(2+3の計算結果としての5)が出力される。

2 Google Driveとの連携

左側のメニューからフォルダのアイコンをクリックするとファイルブラウザが立ち上がる。

その状態で「ドライブをマウント」アイコンをクリックすると、

こんな感じでGoogleドライブへのアクセス権を取得するためのダイアログが出る。ここで「接続」することで、今Colaboratoryを使っているGoogleアカウントのGoogle Driveが接続され、Colaboratory上で直接データの読み出し/書き込みができるようになる。

授業で指定したフォルダを事前に「マイドライブに追加」しておけば、その追加した共有フォルダをColaboratory上から参照できる。

3 追加パッケージのインストールと読み込み

プログラミング言語としてのPythonで開発された機能以外にも、第三者がPythonで使用できる機能を開発して「パッケージ」として提供されている。今回はデータを整理して表示するためによく使われているpandasパッケージ、そしてグラフに日本語を表示できるようにするjapanize_matplotlibパッケージを使用する。

pandasは既にcolaboratory上にインストールされているので

import pandas as pd

で読み込むことができる。これはpandasというパッケージをpdという名前として(=as)インポートすることを意味しており、今後pandasパッケージに含まれる機能は「pd.****」で呼び出すことができるようになる。

一方のjapanize_matplotlibはデフォルトではColabに含まれていないので、新しいセルを作成して

%pip install japanize_matplotlib

を実行してインストールする。

このようにインストールのプロセスが進行し、最後に”Successfully installed japanize-matplotlib”が表示されればOK。

インストールされたら同様にインポートする。

import japanize_matplotlib

これはインポートするだけで自動的に機能するので余計な指定は不要。

4 データの読み込み

指定された授業フォルダ(たとえばMRes2021-共有)までたどり着いたら、開きたいファイルを選んで、ファイル名の右横の三点のボタンを押すと、「ダウンロード」や「ファイル名の変更」と並んで「パスをコピー」というボタンがあるのでこれを選択。

これでそのファイルまでの「場所」がわかったので、それを読み込むべきファイルの場所として指定する。今回はファイルの場所を示す変数「f」と、それを読み込んだ「d」を作ることにする。

f = '/content/drive/MyDrive/MRes2021-共有/pos2021.pkl'

ファイルの場所を示す変数「f」は文字列の変数なので、クオーテーションで囲む必要がある。あとはこれをpandasのread_pickle関数に読み込ませる。

読み込んだデータセットはdisplay()で表示させることができる。

d = pd.read_pickle(f)
display(d)

↓ここまでの操作をまとめるとこんな感じ↓

主な変数

  • ユーザーID:このスーパーマーケットの顧客のうち、ポイントカードを持っている顧客に振られた固有の番号(=いわゆるお客様番号のような)
  • ブランド名:今回分析の対象としているコーヒーのブランド。
  • 数量:その1回の購買で購入された商品の数量。
  • 価格:その商品1点あたりの価格。

これらの変数から、新しい変数を作ることもできる。たとえば単価と数量がわかっているのでそこから一回あたりの合計金額を算出するなら、

d['合計金額'] = d['価格'] * d['数量']

で作成できる。

5 データの集計

授業でも伝えた通り、ビッグデータは全体の傾向を掴むのに長けているが、一方で生のデータをそのまま眺めているだけでそれを理解することは難しい。そこでまずは様々な観点から集計してみることにする。

5.1 データ全体での集計

データ分析の基本として、データの代表値(平均や分散など)の確認から。データをそのまま足し合わせたり平均したりといった集計はdescribe関数を使えば簡単にできる。

d.describe()
  • count:サンプルサイズ
  • mean:算術平均値
  • min/max:最小値 / 最大値
  • 25, 50, 75%:分位点(50%を特に中央値)

describeでは数値変数をすべて集計対象としており、「月」のように集計が意味をなさないものも含まれてしまうので注意。

5.2 顧客ごとの集計

このデータは購入されたある1回の商品ごとのデータになっており、全体の傾向が掴みにくい。理解しやすくするためにもまずは顧客ごとの集計を行ってみる。

特定のグループごとに集計を行う場合にはgroupby関数を用いる。

d.groupby('ユーザーID').sum()

これは今読み込んだデータをgroup by ユーザーID(=顧客IDによってグループ化)した上で、sum(=合計)を計算するコマンド。

先ほどまで同じ顧客が何回も出てきていたデータが顧客ごとに足し合わされ、それぞれが合計何個/いくら購入したのかを表すデータになった。

とはいえ、これは現状でユーザーID順になっているため、金額や個数の多寡はわからない。そこでデータを並び替えてみる。並び替えにはsort_values(‘ソートしたい変数名’)を用いて、

d.groupby('ユーザーID').sum().sort_values('合計金額')

で実行できる。これは昇順になっているが降順にしたければ、sort_valuesのオプションascending=Falseをつける。ascendingは昇順を意味しているため、昇順=否で降順になる。

d.groupby('ユーザーID').sum().sort_values('合計金額', ascending=False)

ちなみにここでは「価格」(=単価)や「月」など合計しても仕方のない変数も一緒に計算されている。pandasでは [[変数名]] という形で必要な変数を選択することができる。試しに数量と合計金額のみを選択した状態で先ほどの処理をやってみるなら、

d[['数量', '合計金額']].groupby('ユーザーID').sum().sort_values('合計金額', ascending=False)

このように、pandasの利点は各処理を関数としてどんどん数珠つなぎにしていけるその操作性の高さにある。

5.3 ブランドごとの集計

上では顧客IDでグループ化したが、同じようにブランドごとに集計をとることもできる。今回は合計ではなく平均meanをとってみる。

d.groupby('ブランド名').mean()

6 データの図示

データに対してplot関数を当てることで様々なグラフを簡単に作成することができる。たとえばブランドごとの期間中の合計数量を出したければplotのbar関数を使って、

brand = d.groupby('ブランド名').sum().sort_values('数量')
brand.plot.bar(y='数量')

*ここでもし日本語がすべて□と表示される場合にはjapanize_matplotlibが正しく読み込めていない。

あるいは月ごとの変化を折れ線グラフで表したければ、groupby(‘月’)で月ごとの合計を作成した上で、plot関数で数量の変化をみる。

d.groupby('月').sum().plot(y='数量')

この折れ線グラフでは5月に数量が極端に落ち込んでいるように見えるが、縦軸が135から始まっていることに注意したい。この軸の範囲も簡単に変更できる。今回はplot関数の中に縦軸(y)の範囲を変更する ylimオプションを付与する。

d.groupby('月').sum().plot(y='数量', ylim=[0, 200])

これでy軸の範囲が0~200に変更された。

7 条件抽出

条件抽出ではデータセットdに対して d[ <条件式> ] の形で指定する。たとえばブランド名がネスレ日本であるサンプルのみを取り出すのであれば、

# 条件抽出:d[ <条件式> ]
# 条 件 式:d['ブランド名'] == 'ネスレ日本'
d[ d['ブランド名'] == 'ネスレ日本' ]

となる。ここで==となっているのは前後の値が一致しているか(各データのブランド名の値がネスレ日本になっているかどうか)を確認する条件式。

これをさらに月次で集計するなら、

d[ d['ブランド名'] == 'ネスレ日本' ].groupby('月').mean()

などで可能。

8 検定

群間の差の検定などを予定。(PW付きの別ページでやります)

9 重回帰分析

重回帰分析を用いたパラメータ推定と解釈などを予定。(PW付きの別ページでやります)