Jupyter Notebookで社内の通話履歴データを分析してみようその1

  • #技術ブログ 

何やら最近、寒いなぁー、ってあらら、前回の更新から2ヶ月経とうとしている!!
もう、師走が近づいているのに相変わらず、ブログさぼり気味のうえピーです。

今回は、「祝」とりあえず、サボらずに「統計検定2級」を受けた記念!!
ということで、「統計検定2級」を受験するために得た知識を使って、社内の通話履歴データを分析してみようと思います。
※なんだか嫌な予感がするので、とりあえずその1にして、1回じゃ終らない感じではじめとこっと。

MySQLで管理している社内の通話履歴をJupyterで管理するので、前提としては、「以前まとめた以下のブログの内容くらい軽く知ってるぜ」です。

  • Jupyter Notebookで分析結果を社内共有!!
  • 猛暑、夏バテ、とりあえずJupyterからMySQLに接続
  • まずは、下準備として、pandas、numpyはどうせ使うんでしょ!と、MySQLへはカッコつけてマジックコマンドでアクセスすることにします。
    あと、matplotlibで出力したグラフを差し込むのは間違いないよねって感じでinlineもしときます。

    In [1]:
    import pandas as pd
    import numpy as np
    import warnings
    %matplotlib inline
    %config SqlMagic.autopandas = False
    %config SqlMagic.feedback = False
    %load_ext sql
    

    よし、OK。エラーなし。
    続いて、通話履歴を管理しているMySQLへ接続して、とりあえず、通話履歴テーブルのレイアウトを出力します。
    ※すいません、通話履歴テーブルのレイアウトはひ・み・つです。

    In [2]:
    %sql mysql+pymysql://秘密のユーザー:秘密のパスワード@秘密のアドレス/秘密のDB名?charset=utf8
    %sql desc 通話履歴テーブル;
    

    おみせできませんが、綺麗に出力されました。
    今回は、通話時間の項目を使って分析したいと思います。
    では、早速、通話履歴データを全量とってきます。

    In [3]:
    rows = %sql select * from 通話履歴テーブル;
    len(rows)
    Out [3]:
    22222
    

    OK。データ数も問題ないので、取得は上手くいったようです。
    このまま、データサイエンティストの必須アイテムpandasのDataFrameに展開します。
    ついでに社内の内線番号で、データにアクセスできるか確認っと。

    In [4]:
    df = rows.DataFrame()
    df['内線番号'][:3]
    Out [4]:
    0    304
    1    401
    2    401
    Name: 内線番号, dtype: object
    

    よし、よし、順調、順調。
    ここで、「統計検定」で得た知識、「各種統計量」を取得してみましょう。

    In [5]:
    print('最小値 =',df['通話時間'].min(),'秒')
    print('平均値 =',df['通話時間'].mean(),'秒')
    print('中央値 =',df['通話時間'].median(),'秒')
    print('最大値 =',df['通話時間'].max(),'秒')
    print('標準偏差 =',df['通話時間'].std(),'秒')
    最小値 = 0 秒
    平均値 = 132.90176401764018 秒
    中央値 = 59.0 秒
    最大値 = 5251 秒
    標準偏差 = 229.39942216580695 秒
    

    ここでちょっとだけ、統計豆知識を。
    平均値は、大小それぞれのはずれ値(通常は発生しないとんでもなく大きな値や小さな値)に、引き摺られてしまうので、中央値も出力して、正しい真ん中の値を把握しましょう!

    ふむふむ、平均は、2分ちょっとですが、中央値は、1分に満たないくらいの値ですね。
    たまにある長電話に平均値が引き摺られているようです。
    社内通話の半分くらいは、1分以内ということは、結構重要な知見かと思います。

    こうなってくると、「第一四分位(25%位置の通話時間)」、「第三四分位(75%位置の通話時間)」、も知りたくなってきます。
    おぉ、さすがpandas、一撃で各種統計量を取得できる関数が存在しております。

    In [6]:
    df['通話時間'].describe()
    Out [6]:
    count    22222.000000
    mean       132.901764
    std        229.399422
    min          0.000000
    25%         20.000000
    50%         59.000000
    75%        151.000000
    max       5251.000000
    Name: 通話時間, dtype: float64
    

    ほう、全体の75%は、2分30秒以内とは、結構意外。
    他の会社の通話も同じ傾向だとすると、案外、音声認識サービスの利用に必要な月の認識時間って短くていいのかも。

    よっしゃ、次は、月ごとの通話履歴数を、ビジュアル化してみようっと。
    とりあえず、録音開始日時だと時間が邪魔だから、月まで保持した項目を追加してみよう。

    In [7]:
    df['録音開始月'] = df['録音開始日時'].dt.strftime('%Y%m')
    

    こんな簡単にオブジェクトに項目追加、pandasサイコー!!

    こっから、どうやってmatplotlibにデータを突っ込もうかな。








    1時間経過。
    なに!?こんな簡単な方法が・・・。
    この1時間は、なんだったんだ・・・。
    というpandas初心者あるあるを経て、こんな感じで簡単にビジュアライズ化できました。

    In [8]:
    df.pivot_table(values='通話時間', index='通話開始月', columns='発着信種別',aggfunc=len)\
        .plot(kind='bar', legend=False, width=1.0, linewidth=1.0, edgecolor='black')\
        .hlines(y=[500,1000,1500,2000,2500,3000], xmin=0, xmax=27, colors='b', linestyles='dashed', linewidths=1)
    out [8]:
    
    
    

    よし、よし、出た出た・・・って、おい、9月の飛び抜けた2500件の着信ってなんだ??
    そんなに問合せあったっけ??

    おぉ、これは、データサイエンティスト見習いに神が与えた試練ですな。

    はっはっは、楽勝だぜ。
    伊達にさっきの1時間無駄足を踏んでいない!!
    通話開始月と内線番号と発着信種別でグルーピングして、describeすればいいんだろ。
    そんで、9月を抽出じゃい。
    どうだ!?

    In [9]:
    g_month_exten = df.groupby(['通話開始月','内線番号','発着信種別']).describe()['通話時間']
    g_month_exten.loc['201809']
    Out [9]:
    
    ~省略~
    
    

    ふむ、401~405の社内で使っていない番号の通話数が異常に多い。
    テスト通話を頻繁に実施したようですね、というわけで今日はここまで。

    いやー、pandas使いこなすにはまだまだ、経験が不足していることがよく分かったのが今回一番の収穫。
    See、you!!