直播数据分析

针对douyu_60937 直播间 (2018/11/19 19:04:18 - 2018/11/20 7:56:42) 这个时间段的数据分析

基础数据展示

clipboard.png
以上数据是从直播间的弹幕中提取的相关数据,每个字段解释为

 {
    '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)

clipboard.png

根据牌子名称统计最大值、最小值、平均值

  • 计算牌子的最大值、最小值、平均值的时候需要根据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())

clipboard.png

{'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())

clipboard.png

{'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)

clipboard.png

{'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}}

每小时发言数量

  • 根据时间统计需要构造一个datetime 数据类型的列 , 利用 resample("时间标识符") + count() 进行统计
  • 为了后续制图方便我在这里直接把 <class 'pandas._libs.tslibs.timestamps.Timestamp'> 转换成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

clipboard.png

{'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}}

每小时在线人数(发言人)

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)

clipboard.png

{'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()

dengji

粉丝牌占比 饼图

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('粉丝牌占比 \n(2018/11/19  19:04:18 - 2018/11/20  7:56:42)')
    plt.savefig("粉丝牌占比.jpg")
    plt.show()

zhanbi

用户等级分布 折线图


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("用户等级情况\n(2018/11/19  19:04:18 - 2018/11/20  7:56:42)")
    plt.savefig("用户等级情况.jpg")
    plt.show()

dengjiqk

每个时间段用户以及弹幕量 折线图


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("每个时间段用户以及弹幕量\n(2018/11/19  19:04:18 - 2018/11/20  7:56:42)")
    plt.savefig("每个时间段用户以及弹幕量.jpg")
    plt.show()

dengji


huifer
483 声望4 粉丝