IT業務効率化

pandasで縦のデータを月別で横に集計する

依頼主分析がしたい

私の会社ではBacklogを利用して仕事を管理しています。

運用作業(ヘルプデスク作業に近い)は多種多様な依頼をこなし、対応しなくてはいけないことが様々です。これを分析して少しでも傾向を掴み、事前の対策につなげようと思います。

pandasで縦のデータを横に集計する

pandas 縦 横左から順に、依頼日、依頼者、部署

依頼は日々ランダムな人・部署・時間で来ます。これを

  • 月ごとの依頼件数で集計
  • 部署ごと・依頼主ごとに集計

することを目指します。

pandas 依頼者

このようなイメージの集計を目指します。

こうすることでtanakaさんの依頼が増え続けていることや、tanaka・suzukiさんの依頼が多いので、2人に普段の困りごとを聞いて事前に依頼を潰しておけるかもしれません。

ここまで長々と概要を説明したのは、pandasを用いた横列の集計や行列転地など似たような記事が多いからです。本記事に関しては上記のようなニーズに答えます。それでは大変お待たせいたしましたが、コードが次節です。

pivot_tableを使って縦列のデータを集計する

import pandas as pd
import japanize_matplotlib  # 日本語でもプロットできるようにインポート
from jupyterthemes import jtplot
jtplot.style(theme='monokai')  # jupyter themesでダークモードを利用している
%matplotlib inline

def aggregate_df_by_month(df_for_aggr, col_to_be_aggr, col_of_date):
    df_excluded_useless  = df_for_aggr[[col_to_be_aggr,col_of_date]].set_index(col_of_date)
    # ベストプラクティスが疑問
    df_excluded_useless["year_month"] = df_excluded_useless.index.year.astype("str") \
                                                        + df_excluded_useless.index.month.astype("str")
    
    group = df_excluded_useless.groupby(["year_month", col_to_be_aggr])
    group_df = pd.DataFrame(group.size()).reset_index(col_to_be_aggr)
    group_df_T = group_df.pivot_table(values=0,  # 0はsize()によって自動生成されたカラム名が0のため
                                                                    index=group_df.index, 
                                                                    columns=[col_to_be_aggr], aggfunc='sum')  
    group_df_T_added_index = group_df_T.set_index(pd.to_datetime(group_df_T.index, format='%Y%m'))
    plot_df = group_df_T_added_index.fillna(0)
    plot_df.plot(figsize=(16,8), alpha=0.5)

df = pd.read_csv("Backlog-Issues.csv")
df["request_date"] = pd.to_datetime(df["request_date"] )
aggregate_df_by_month(df, "orderer", "request_date")

解説(マサカリお待ちしております)

関数aggregate_df_by_month

日付ごとで集計する関数。引数はDataFrame、y軸に相当する集計する列、x軸に相当する時間(型はあらかじめ日付型にしておく)です。一旦関数としては月ごとに集計できるような機能におさめておきます。

日付を月まで切った列を追加する

df_excluded_useless["year_month"] = df_excluded_useless.index.year.astype("str") \
                                                        + df_excluded_useless.index.month.astype("str")

月までを基準にソートしたり集計する関数はあると思いますが、この後のpivot_tableで活きてきます。

件数を取得してデータフレームを作り直す

    group = df_excluded_useless.groupby(["year_month", col_to_be_aggr])
    group_df = pd.DataFrame(group.size()).reset_index(col_to_be_aggr)

月ごとで集計対象の列(col_to_be_aggr)を集計し、group.size()でインデックスに指定している月まで日付(例;201908)あたりの件数を表示します。2行目で普通にDataFrameに入れようとしただけではcol_to_be_aggrがindexに入ってしまうので、reset_indexでindexから外します。

横列になっているデータをpivot_tableで縦にする

    group_df_T = group_df.pivot_table(values=0,  # 0はsize()によって自動生成されたカラム名が0のため
                                      index=group_df.index, 
                                      columns=[col_to_be_aggr], aggfunc='sum')  

※values=0は少々別の書き方をするべきかと考えています…

プロットする

    group_df_T_added_index = group_df_T.set_index(pd.to_datetime(group_df_T.index, format='%Y%m'))
    plot_df = group_df_T_added_index.fillna(0)
    plot_df.plot(figsize=(16,8), alpha=0.5)
ABOUT ME
hirayuki
今年で社会人3年目になります。 日々体当たりで仕事を覚えています。 テーマはIT・教育です。 少しでも技術に親しんでもらえるよう、noteで4コマ漫画も書いています。 https://note.mu/hirayuki