pandas&matplotlib生放送データ分析


生放送データ分析
douyuに対して60937生中継室(2018/11/19 19 19:04:18-2018/11/20 7:56:42)この時間帯のデータ分析
基礎データ展示
以上のデータは生中継間の弾幕から抽出された関連データであり,各フィールドは
 {
    'id': '    ',
    'user': '   ',
    'cont': '     ',
    'level': '    ',
    'sign': '  ',
    'sign_leve': '    ',
    'rid': '     ',
}

に頼る
pandas==0.23.4
matplotlib==3.0.2
numpy==1.15.4
datetime

データしょり
基礎準備
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import datetime

path = "douyu_60937.xlsx"
data = pd.read_excel(path)

ブランド名による最大値、最小値、平均値の統計
  • ブランドの最大値、最小値、平均値を計算する場合はuserに基づいて重複項目を削除し、
  • の複数回の計算を避ける必要がある.
  • 図を作成する必要があります.戻り値をdict()
  • に設定します.
    t = data[['user', 'sign', 'sign_leve']].drop_duplicates(subset=['user'])  #       
    t = data.groupby('sign').sign_leve.agg(['mean', 'min', 'max'])
    t.sort_values(['max'], ascending=False, inplace=True)
    print(t)
    print(t[:20].to_dict())
    {'mean': {'   ': 11.848837209302326, '196': 16.475254730713246, '  ': 11.418693982074263, 'Amss': 10.0, '   ': 26.0, '   ': 9.93750495049505, '339': 18.941176470588236, '   ': 24.0, '  ': 7.768361581920904, '   ': 12.676724137931034, '  ': 10.416666666666666, '  ': 7.059241706161138, '   ': 10.718562874251496, 'S1un': 22.0, '   ': 9.938271604938272, '   ': 7.909323116219668, '   ': 8.377464788732395, '   ': 5.686131386861314, '   ': 7.034911587538053, ' Q': 21.0}, 'min': {'   ': 2, '196': 4, '  ': 3, 'Amss': 4, '   ': 26, '   ': 1, '339': 12, '   ': 24, '  ': 1, '   ': 3, '  ': 6, '  ': 1, '   ': 2, 'S1un': 22, '   ': 1, '   ': 1, '   ': 1, '   ': 3, '   ': 1, ' Q': 21}, 'max': {'   ': 30, '196': 30, '  ': 30, 'Amss': 27, '   ': 26, '   ': 25, '339': 25, '   ': 24, '  ': 23, '   ': 23, '  ': 22, '  ': 22, '   ': 22, 'S1un': 22, '   ': 22, '   ': 22, '   ': 22, '   ': 22, '   ': 21, ' Q': 21}}

    ブランド名による数量の集計
  • 分類統計の場合、カラム名を変更するにはrename(column={'古いカラム名':'新しいカラム名'})
  • を使用します.
    sign_max_count = data[['user', 'sign', 'sign_leve']].drop_duplicates(subset=['user'])  #       
    sign_max_count = data[['sign']].groupby(['sign']).agg({'sign': 'count'}).rename(
        columns={'sign': 'sign_count'})
    sign_max_count.sort_values(['sign_count'], ascending=False, inplace=True)
    print(sign_max_count)
    print(sign_max_count[:20].to_dict())
    {'sign_count': {'   ': 15439, '   ': 12625, '   ': 1566, '196': 1374, '  ': 781, '   ': 640, '   ': 429, '  ': 422, '   ': 405, ' 8 ': 397, '   ': 370, '   ': 355, '   ': 355, '   ': 343, '   ': 243, '   ': 232, '   ': 187, '  ': 184, '  ': 177, '   ': 173}}
    

    各レベルのユーザー数の統計
    now_data = data[['user', 'level']].drop_duplicates(subset=['user'])  #       
    now_data = data[['level']].groupby(['level']).agg({'level': 'count'}).rename(
        columns={'level': 'level_count'})
    now_data.sort_values(['level_count'], ascending=False, inplace=True)
    {'level_count': {16: 3159, 19: 3122, 17: 3086, 21: 2984, 18: 2882, 15: 2832, 22: 2624, 23: 2564, 20: 2545, 13: 2379, 14: 2308, 24: 2274, 11: 2066, 12: 1894, 7: 1781, 9: 1753, 10: 1690, 8: 1678, 5: 1645, 25: 1554}}

    1時間あたりの投稿数
  • 時間統計に基づいてdatetimeデータ型の列を構築し、resample(「時間識別子」)+count()を用いて統計
  • を行う.
  • 後続製図の便宜上python内蔵datetimeクラスに直接変換する方法はto_pydatetime
  • df = data
    df = df.loc[:, ('cont', 'uptime')]
    df = df.set_index('uptime')
    result = df.resample('H').count().rename(columns={'cont': 'user_count'})
    print(result)
    result = result.to_dict()
    
    s = {}
    for k, v in result['user_count'].items():
        s[k.to_pydatetime()] = v
    result['user_count'] = s
    
    print(result)
    return result
    {'user_count': {datetime.datetime(2018, 11, 19, 19, 0): 12707, datetime.datetime(2018, 11, 19, 20, 0): 12374, datetime.datetime(2018, 11, 19, 21, 0): 19340, datetime.datetime(2018, 11, 19, 22, 0): 13530, datetime.datetime(2018, 11, 19, 23, 0): 8, datetime.datetime(2018, 11, 20, 0, 0): 2, datetime.datetime(2018, 11, 20, 1, 0): 1, datetime.datetime(2018, 11, 20, 2, 0): 0, datetime.datetime(2018, 11, 20, 3, 0): 0, datetime.datetime(2018, 11, 20, 4, 0): 5, datetime.datetime(2018, 11, 20, 5, 0): 1, datetime.datetime(2018, 11, 20, 6, 0): 11, datetime.datetime(2018, 11, 20, 7, 0): 23}}

    1時間あたりのオンライン人数(スポークスマン)
    df = data.drop_duplicates(subset=['user'])
    df = df.loc[:, ('user', 'uptime')]
    df = df.set_index('uptime')
    result = df.resample('H').count().rename(columns={'user': 'user_count'})
    print(result)
    result = result.to_dict()
    s = {}
    for k, v in result['user_count'].items():
        s[k.to_pydatetime()] = v
    result['user_count'] = s
    print(result)
    {'user_count': {datetime.datetime(2018, 11, 19, 19, 0): 4223, datetime.datetime(2018, 11, 19, 20, 0): 2207, datetime.datetime(2018, 11, 19, 21, 0): 3843, datetime.datetime(2018, 11, 19, 22, 0): 1875, datetime.datetime(2018, 11, 19, 23, 0): 6, datetime.datetime(2018, 11, 20, 0, 0): 0, datetime.datetime(2018, 11, 20, 1, 0): 1, datetime.datetime(2018, 11, 20, 2, 0): 0, datetime.datetime(2018, 11, 20, 3, 0): 0, datetime.datetime(2018, 11, 20, 4, 0): 1, datetime.datetime(2018, 11, 20, 5, 0): 1, datetime.datetime(2018, 11, 20, 6, 0): 1, datetime.datetime(2018, 11, 20, 7, 0): 4}}

    グラフを作成
    ファンカード等級状況柱状図
    def autolabel(ax, rects, xpos='center'):
        xpos = xpos.lower()
        ha = {'center': 'center', 'right': 'left', 'left': 'right'}
        offset = {'center': 0.5, 'right': 0.57, 'left': 0.43}
    
        for rect in rects:
            height = rect.get_height()
            ax.text(rect.get_x() + rect.get_width() * offset[xpos], 1.01 * height,
                    '{}'.format(height), ha=ha[xpos], va='bottom')
    
    
    def sign_bar_wiht_leve(t1):
        """
                  
        :return:
        """
        mean = [round(x, 1) for x in t1['mean'].values()]
        min = t1['min'].values()
        max = t1['max'].values()
        ind = np.arange(len(mean))
        width = 0.35
        fig, ax = plt.subplots()
        rects_2 = ax.bar(ind, min, width / 2, color='IndianRed', label='    ')
        rects_1 = ax.bar(ind + width / 2, mean, width / 2, color='SkyBlue', label='    ')
        rects_3 = ax.bar(ind + width, max, width / 2, color='Black', label='    ')
        ax.set_ylabel('  ')
        ax.set_title('      (2018/11/19  19:04:18 - 2018/11/20  7:56:42)')
        ax.set_xticks(ind)
        ax.set_xticklabels(t1['mean'].keys())
        ax.legend()
        fig = plt.gcf()
        fig.set_size_inches(30, 10.5)
        autolabel(ax=ax, rects=rects_1, xpos="center")
        autolabel(ax=ax, rects=rects_2, xpos="center")
        autolabel(ax=ax, rects=rects_3, xpos="center")
        fig.savefig("     .jpg")
        fig.show()
    

    ファンカード占比餅図
    def sign_pie_with_count(t2):
        """
             
        :param t2:
        :return:
        """
        sizes = list(t2['sign_count'].values())[:5]
        labels = list(t2['sign_count'].keys())[:5]
        plt.figure(figsize=(8, 4))  #       
        explode = (0, 0, 0, 0)  #         ,           
        patches, text1, text2 = plt.pie(sizes,
                                        labels=labels,
                                        autopct='%3.2f%%',  #          
                                        shadow=False,  #      
                                        startangle=90,  #          
                                        pctdistance=0.8)  #            
        plt.axis('equal')
        plt.legend()
        plt.title('      
    (2018/11/19 19:04:18 - 2018/11/20 7:56:42)') plt.savefig(" .jpg") plt.show()

    ユーザレベル分布折れ線グラフ
    
    def user_line_with_count(t4):
        """
                 
        :param t4:
        :return:
        """
        t4 = sorted(t4['level_count'].items(), key=lambda d: d[0])
    
        x = [i[0] for i in t4]
        y = [i[1] for i in t4]
    
        plt.figure(figsize=(8, 4))
        plt.plot(x, y, "b--", linewidth=1)
    
        #       
        for a, b in zip(x, y):
            plt.text(a, b, b, ha='center', va='bottom', fontsize=10)
    
        plt.xlabel("    ")
        plt.ylabel("  ")
        plt.title("      
    (2018/11/19 19:04:18 - 2018/11/20 7:56:42)") plt.savefig(" .jpg") plt.show()

    各期間のユーザーおよび弾幕量の折れ線図
    
    def show_label(x, y, plt):
        #       
        for a, b in zip(x, y):
            plt.text(a, b, b, ha='center', va='bottom', fontsize=10)
    
    
    def user_time(t5, t6):
        """
                    
        :param t5:
        :param t6:
        :return:
        """
        t_5 = {k.strftime("%Y-%m-%d %H"): v for k, v in t5['user_count'].items()}
        t_6 = {k.strftime("%Y-%m-%d %H"): v for k, v in t6['user_count'].items()}
    
        x_1 = t_5.keys()
        y_1 = t_5.values()
    
        x_2 = t_6.keys()
        y_2 = t_6.values()
    
        plt.figure(figsize=(9, 5))
        plt.plot(x_1, y_1, "o-", linewidth=1, label='    ')
        plt.plot(x_2, y_2, "g--", linewidth=1, label='    ')
        show_label(x_1, y_1, plt)
        show_label(x_2, y_2, plt)
        plt.xticks(rotation=30)
        plt.legend()
    
        plt.xlabel("  ")
        plt.ylabel("  ")
        plt.title("            
    (2018/11/19 19:04:18 - 2018/11/20 7:56:42)") plt.savefig(" .jpg") plt.show()