はじめに
今回は前回に引き続き、pandasのpivot_table()による集計を扱います。前回の投稿で、データを求められる状況によっては、pivot_table()で集計したままのデータでは十分ではないケースもあることをお伝えしました。今回は、それを解決する方法をお伝えします。
前回の投稿は以下からご確認ください。
やりたいこと
前回の投稿で、店舗ごとの月別・商品カテゴリ別の受注件数をpivot_table()メソッドを使って集計しました。その際に以下の注意点がありました、
ここに記載した、「月ごとの商品カテゴリが揃っていない」「すべての店舗が表示されていない」のは、扱いづらい場合もあると思います。今回は、各店舗や対象月・対象商品カテゴリにおける受注実績の有無に関わらず、「商品カテゴリを揃える」「すべての店舗を表示させる」ことにしましょう。
商品カテゴリを揃える
まずは商品カテゴリから揃えていくことにしましょう。pivot_table()メソッドで集計する際に、揃えたい列が階層型にならないようにします。こうすることで、コードの2行目にあるように列の指定が容易になります。
_=pd.pivot_table(connect,index=['受注月','店舗'],columns='商品カテゴリ',values='受注件数',aggfunc='sum') tmp=_.loc[:,['オフィス用品','家具','文具','生活用品','パソコン']] tmp
まずは商品カテゴリがすべて表示されて、指定したとおりに並べる頃ができました。ここから列方向で各月を比較できるように変形していきます。行から列にフィールドを移動させるには、unstack()メソッドでしたね。
tmp=tmp.unstack(0).swaplevel(0,1,axis=1) tmp
列は第一階層に「受注月」第二階層に「商品カテゴリ」となっています。但し、並び順が変ですね。月ごとに商品カテゴリが並ぶようにしましょう。次のように第一階層の並び順を指定すればよいです。
tmp=tmp[['10月','11月','12月','1月']] tmp
これで各月ごとに商品カテゴリを揃えて集計することができました。次にすべての店舗を表示させることにしましょう。
すべての店舗を表示させる
まずは何故、D店舗が表示されないのかを突き止めましょう。D店舗の会員を調べてみることにします。
customer_data.query('店舗=="D店舗"')
D店舗の会員は「C0005」「C0015」の2名だとわかります。この方たちの受注実績があるかを見てみましょう。
order_data.query('会員No.isin(["C0005","C0015"])')
受注実績には、D店舗の会員による受注のレコードはありませんでした。どうやらD店舗の会員による受注実績がないため、pivot_table()による集計ではD店舗が表示されていないようです。
実績がなくても店舗がすべて表示されるように店舗マスタを作って左外部結合をするようにしましょう。
# 店舗マスタの作成 store_master=pd.DataFrame({'店舗':customer_data['店舗'].unique()}).sort_values(by='店舗') # 店舗マスタの結合 store_all=pd.merge(store_master,tmp,on='店舗',how='left') store_all
これでD店舗も表示させることができました。ただ、もともと階層を持っていたカラムの表示が少し変ですね。この部分を再び、列に対する階層型インデックスを設定するようにしましょう。
まずは店舗の列をインデックス化して、カラムには階層を持たせたい列の組み合わせが表示された状態にしましょう。
store_all=store_all.set_index('店舗') store_all
列はよく見ると、(受注月, 商品カテゴリ)という表記になっていますね。これを取り出してリストを作り、列に対する階層型インデックスを設定すればよさそうです。やってみましょう。
# 列名を取り出す columns_list=store_all.columns # 受注月/商品カテゴリを格納するリストの準備 month_list=[] item_list=[] for i in range(len(columns_list)): month_list.append(columns_list[i][0]) item_list.append(columns_list[i][1]) multi_columns=[month_list,item_list] result=pd.DataFrame(store_all,columns=multi_columns) result
最後に合計の行・列を加えておきましょう。
result['合計']=result.sum(axis=1) result.loc['合計',:]=result.sum(axis=0) result
店舗ごとに月別・商品カテゴリ別の受注件数を集計することができました。
まとめ
いかがでしたか?このように集計した表を整形する作業が生じることがあります。stack()/unstack()やswaplevel()などを使いこなせると、割と自由自在に表を整形できるようになります。また、単純にpivot_table()で集計したときには、状況によっては十分ではないことがあります。求められるデータがどのようなものなのかを意識して、集計するようにしましょう。お疲れさまでした。
▶ ピボットテーブルの基本的な使い方は以下をご覧ください。
コメント