Jupyter Notebookで社内の通話履歴データを分析してみようその1
何やら最近、寒いなぁー、ってあらら、前回の更新から2ヶ月経とうとしている!!
もう、師走が近づいているのに相変わらず、ブログさぼり気味のうえピーです。
今回は、「祝」とりあえず、サボらずに「統計検定2級」を受けた記念!!
ということで、「統計検定2級」を受験するために得た知識を使って、社内の通話履歴データを分析してみようと思います。
※なんだか嫌な予感がするので、とりあえずその1にして、1回じゃ終らない感じではじめとこっと。
MySQLで管理している社内の通話履歴をJupyterで管理するので、前提としては、「以前まとめた以下のブログの内容くらい軽く知ってるぜ」です。
まずは、下準備として、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!!