用Python告诉你,谁是这个夏天的最强乐队?

文章转载自公众号

猪栏守望者 , 作者 数据守望者

虽然现在大众的兴趣非常的分散,乐队的夏天是否是今天最火的综艺节目,每个人心中的答案都是不一样的。但在我看来,我很感谢有这么一个节目,可以让我接触到不同类型的音乐,认识这么多优秀的乐队,知道坚持做自己喜欢的事是一件多么幸福的事。

我本身从事数据分析相关的工作,业余时间学习Python,今天应该是连续学习打卡的第84天,希望通过这个分析,可以提升代码水平,同时也想挖掘一些隐藏在排名,得分这些数据底下的结论,同时为喜欢的节目打call,最后我将预测最后一期Hot5的名单。写这篇文章的时候,距离播出还有3小时,时间紧迫哈哈,很快就要打脸了。

好了,说了这么多,那么开始吧!

第一步:数据采集

数据分析数据分析,没有数据就没有分析。网络上没有公开的详细得票、排名数据,只好自己整理了。首先购买爱奇艺会员

,不然很长时间都消耗在广告上了。然后用2.5倍速播放(这么听歌还挺带感的),然后看到这一幕,按住锁屏和音量键+,咔嚓,数据收集到了!

最后手机相册就变成现在这样

最后再填到一个Excel表里面,数据就有啦!

(如果想要原始数据,关注公众号回复“乐队的夏天”可以下载)

它大概长这个样子?

一共有5个sheet,对应5场比赛,字段分别是:[场数, 出场顺序, 乐队, 歌曲, 超级乐迷得分, 专业乐迷得分, 大众乐迷得分, 总得分, 排名, 是否晋级下一轮]

第二步:读取数据

在读取数据之前,先导入分析的工具包

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

为了显得有一点点审美,我用取色器取了乐队的夏天主KV上面的颜色,便于后面可视化来使用。

# 配置乐队的夏天主题色

purple = (0.22,0.09,0.59) # 紫色
yellow = (0.99,0.89,0.27) # 黄色
green = (0.36,0.94,0.55) # 绿色
blue = (0.06,0.24,0.78) # 蓝色
red = (0.98,0.31,0.36) # 红色

环境设置完了,第一步是导入数据

# 读取数据

data1 = pd.read_excel('/.../乐队的夏天.xlsx','第一场')
data2 = pd.read_excel('/.../乐队的夏天.xlsx','第二场两两PK赛')
data3 = pd.read_excel('/.../乐队的夏天.xlsx','第三场累计积分赛')
data4 = pd.read_excel('/.../乐队的夏天.xlsx','第四场复活赛')
data5 = pd.read_excel('/.../乐队的夏天.xlsx','第五场9进7')

观察一下数据吧

# 观察数据

data1.info()
data1.head()

以第一场的数据为例为例,可以看到字段和数据的行数,其中得分有(31-27=4)行数据为空,进入第三步。

第三步:数据清洗

既然有空数据,先看看是怎么回事

# 可以看到有四只乐队是没有得分和排名的,把他们列出来

data1[data1['总得分'].isnull()]

所以其实是有31只乐队表演的,但这四只乐队因为被剪掉了,所以没有具体成绩的数据,怎么办呢,只好把你们删了。

data1 = data1.dropna(axis = 0)

这样就完成了,因为数据是自己手动录入的,所以其它没什么问题了,可以开始分析了。

第四步:数据分析

整体的分析思路遵循从整体到局部的顺序,分为乐队和歌曲两个部分,再细分超级乐迷,专业乐迷和大众乐迷三个角度。同时会展示乐队在每期比赛的排名升降情况。

另外由于每场比赛的总票数不同,不同评委票数比例不同,为了使得不同场次之间的得票数据具备可比性,需要用到两种数据标准化的方法,分别是:

  1. Z_score 标准分
  2. 0-1 normalization 归一分

Z_score标准分的计算方法是用

(该乐队当场得分 - 当场所有乐队得分的平均数)/ 当场所有乐队得分的标准差

计算得到

# 标准分函数定义

def z_score_normalize(series):
  mean = series.mean()
  std_dv = series.std()
  return series.apply(lambda x:(x - mean) / std_dv)
  
# 用循环的方式批量对每场比赛的得分做处理

competition = [data1,data2,data3,data4,data5]

for period in competition:
    period['超级乐迷得分_标准分'] =  z_score_normalize(period['超级乐迷得分'])
    period['专业乐迷得分_标准分'] =  z_score_normalize(period['专业乐迷得分'])
    period['大众乐迷得分_标准分'] =  z_score_normalize(period['大众乐迷得分'])
    period['总得分_标准分'] =  z_score_normalize(period['总得分'])
  

0-1 normalization 归一分的计算方法是用

乐队得票数/总票数 计算得到,也等于常说的得票率

# 定义归一化的函数

def normalize(series,x_max):

    return series.apply(lambda x: x/x_max)
# 对不同总分不同类别的得分应用归一化函数

for data in [data1,data2,data5]:
    data['超级乐迷_归一分'] = normalize(data['超级乐迷得分'],50)

data3['超级乐迷_归一分'] = normalize(data3['超级乐迷得分'],60)
data4['超级乐迷_归一分'] = normalize(data4['超级乐迷得分'],40)

for data in [data1,data2,data3,data4,data5]:
    data['专业乐迷_归一分'] = normalize(data['专业乐迷得分'],40)
    
for data in [data1,data2]:
    data['大众乐迷_归一分'] = normalize(data['大众乐迷得分'],100)
for data in [data3,data4,data5]:
    data['大众乐迷_归一分'] = normalize(data['大众乐迷得分'],360)

做完上面两步,再把每场的数据拼成一个表,大功告成。(此处省略拼接代码)

total_score

首先我们分析乐队,通过27只乐队在目前5场比赛中所表演的曲目的总得分的标准分的平均分,来衡量乐队的整体表现。

这个数据首先反映乐队的歌在该场比赛中的表现,其次结合多场比赛歌曲的表现,体现乐队的整体成绩。

# 按照乐队这个标签分类计算,计算方式是平均值,计算字段是总得分_标准分,然后按照总得分_标准分排列

total_score_mean = total_score.groupby(['乐队'])[['总得分_标准分']].mean().sort_values(
    by = '总得分_标准分',ascending = False)
total_score_mean

(贴一部分成绩出来)

然后把这个结果可视化看看

# 对乐队总得分_标准分做可视化

y = np.arange(len(total_score_mean.index))
x = np.array(list(total_score_mean['总得分_标准分']))
fig,ax = plt.subplots(figsize = (12,12))
total_score_mean.plot.barh(ax=ax,alpha=0.7,title='27只乐队场均表现',color = 'g')
for a,b in zip(x,y):
    plt.text(a, b, '%.2f' % a, ha='center', va= 'center',fontsize=12)
ax.grid(False)

新裤子排名第一,这也是在意料之中,生命因你而火热,花火这几首歌在朋友圈都爆了,其他的像刺猬、九连真人、盘尼西林、旅行团、Click#15都表现很稳定,在目前的晋级名单中。但有两支乐队比较奇怪,一个是一度被淘汰的痛痒乐队,竟然排在第二,另一个是一直在线,还把痛痒PK掉的面孔,排名甚至不在前10。

# 把痛痒的成绩拉出来看一下 
total_score[total_score['乐队'] == '痛痒乐队']

<再见杰克>和<西湖>都在当轮比赛中取得非常突出的表现,但<我愿意>真的可惜了。

total_score[total_score['乐队'] == '面孔乐队']

较于其他只表演了一场但排名中等的队伍,面孔因被<张三的歌>垫底,一举拖垮,也因此惨遭淘汰。

接下来 我想研究,在超级乐迷、专业乐迷和大众乐迷各自眼里,哪些乐队是他们喜欢的,他们共同喜欢的,和差异很大的乐队分别是哪些?

# 代码逻辑和前面选总得分作为计算字段的逻辑一样,只不过这次选取单个群体得分作为指标

super_score_mean = total_score.groupby(['乐队'])[['超级乐迷得分_标准分']].mean().sort_values(
    by = '超级乐迷得分_标准分')
pro_score_mean = total_score.groupby(['乐队'])[['专业乐迷得分_标准分']].mean().sort_values(
    by = '专业乐迷得分_标准分')
public_score_mean = total_score.groupby(['乐队'])[['大众乐迷得分_标准分']].mean().sort_values(
    by = '大众乐迷得分_标准分')

对前10的乐队进行数据可视化

fig,ax = plt.subplots(1,3,figsize = (16,6))

super_score_mean.tail(10).plot.barh(ax=ax[0],color = '#dc2624',alpha=0.7,title='超级乐迷心中TOP10',grid=False)
pro_score_mean.tail(10).plot.barh(ax=ax[1],color = '#2b4750',alpha=0.7,title='专业乐迷心中TOP10',grid=False)
public_score_mean.tail(10).plot.barh(ax=ax[2],color = '#649E7D',alpha=0.7,title='大众乐迷心中TOP10',grid=False)
同时在三个群体中位列心目前十的乐队是:
 {'九连真人', '海龟先生', '刺猬', '盘尼西林', '新裤子'}

下面一起来读绕口令:

在超级乐迷心中前十,但不在专业乐迷心中的前十乐队是:
 {'痛痒乐队', '面孔乐队', '鹿先森'}

在超级乐迷心中前十,但不在大众乐迷心中的前十乐队是:
 {'Mr.WooHoo', 'Click#15', '面孔乐队', '鹿先森'}

在专业乐迷心中前十,但不在超级乐迷心中的前十乐队是:
 {'Mr.Miss', '和平和浪', '皇后皮箱'}

在专业乐迷心中前十,但不在大众乐迷心中的前十乐队是:
 {'Click#15', '皇后皮箱', 'Mr.Miss', '和平和浪', 'Mr.WooHoo'}

在大众乐迷心中前十,但不在超级乐迷心中的前十乐队是:
 {'旅行团乐队', '黑撒乐队', '葡萄不愤怒', '南无乐队'}

在大众乐迷心中前十,但不在专业乐迷心中的前十乐队是:
 {'旅行团乐队', '葡萄不愤怒', '南无乐队', '痛痒乐队', '黑撒乐队'}

(上面的内容是通过对三个数据做集合运算得出的,完整代码在点击阅读原文)

需要说明的是,因为有些乐队在第一轮就被淘汰了,例如鹿先森、和平和浪、葡糖不愤怒,使得他们单场表现的成绩就代表了他们的整体水平,这是有失偏颇的,因为比赛本身是淘汰和晋级的形式,越往后面对的竞争环境会越加激烈,所以得分会更能代表乐队实力。

接下来对比较熟悉的9只乐队的每期排名做可视化,直观地展现他们在每期表现的升降。

新裤子的发挥是较为稳定的,除了第三场上和Cindy合作的音乐形式较为新颖,让观众一时难以接受之外,在各个场次都获得非常靠前的成绩。

同样稳定的还有九连真人,一直稳稳的在中间,此外第二场改编李宗盛大哥的凡人歌,现场炸裂,表现超出期待。

表现越来越好的有两只乐队:

1.刺猬

2.Click#15

刺猬可谓是低开高走,复活赛中凭借白日梦蓝稳稳防守住黑撒乐队的挑战,女神赛中和斯斯与帆的合作更是获得了全场最佳。

Click#15虽然在第二场和面孔的PK赛中被淘汰,但又杀了回来,而且第五场演绎beyond的碑面派对,首次赢得第一名。

另外面孔乐队的处境一直比较尴尬,看他们的音乐对这一代人确实存在一些隔阂。

最后还有我很喜欢的乐队,海龟先生。第一场比赛在31只乐队中位列第一,后面他们做了许多创意,还有想通过音乐表达自己的想法,可惜没有被buy in.

对乐队的分析暂时告一段落,接下来看看歌曲。

通过前面提到的归一化计算,可以得到一下数据

(此处省略了一部分代码,完整代码在点击阅读原文

首先对数据整体有一个把握

# 看看数据整体的描述
total_nor_score.describe()

# 运用箱型图可以看到各组给分的分布,其中蓝线是平均分,圆圈是最小值
fig,ax = plt.subplots(1,1,figsize = (8,4))
total_nor_score.boxplot(ax = ax,grid=False)

从上面的图和数据不难看出,超级乐迷给分的范围相对较高,也就是所谓的手松,而专业乐迷擅长给低分,最低的时候只给出了20%比例的票,大众乐迷相对克制,最高分也仅仅给出了92%的票,所谓的众口难调。总得分的平均数是0.71,意味着所有歌曲平均下来能拿到71%的票,也是挺不容易的。

再来看看,得票率前10的歌曲吧!

top10_songs = total_nor_score.sort_values(by = '总得分_归一分').tail(10)
top10_songs.plot.barh(x='歌曲',y='总得分_归一分',color=purple)
print('截止第五期,最受欢迎的10首歌分别是:\n',list(top10_songs['歌曲']))

截止第五期,最受欢迎的10首歌分别是: ['一场游戏一场梦', "Don't break my heart", '红河谷', '凡人歌', 'How come u leave me like this', '生命因你而火热', '椑面派对', '西湖', '花火', 'Bye Bye']

下面看看在每组评委心目中前10的歌曲:

total_nor_score.sort_values(by = '超级乐迷_归一分').tail(10).plot.barh(x='歌曲',y='超级乐迷_归一分',color=red)
total_nor_score.sort_values(by = '专业乐迷_归一分').tail(10).plot.barh(x='歌曲',y='专业乐迷_归一分',color=yellow)
total_nor_score.sort_values(by = '大众乐迷_归一分').tail(10).plot.barh(x='歌曲',y='大众乐迷_归一分',color=green)

超级乐迷最喜欢Don't break my heart,专业乐迷最喜欢Bye Bye Bye,大众乐迷最喜欢西湖。

整体回顾完了,最后单独分析两个问题。第一个是为什么<我愿意>这首歌表现不好呢?

total_nor_score[total_nor_score['歌曲'] == '我愿意']

可以看到虽然在节目中,矛头似乎指向了专业乐迷,但实际上,专业乐迷给票的比例比大众乐迷是要高的,真正不喜欢的是大众乐迷,只给出了一半的票数。

第二个问题是,谁在不喜欢海龟先生?

total_nor_score_t = pd.merge(total_nor_score, total_score[['乐队','歌曲']], on='歌曲')
total_nor_score_t[total_nor_score_t['乐队'] == '海龟先生']

咿呀呀这首歌拖累了海龟的整体平均分,而在这首歌中,专业乐迷给票的比例是最低的。

看看每组分别对海龟先生的作品给出的平均分:

total_nor_score_t[total_nor_score_t['乐队'] == '海龟先生'].mean()
超级乐迷_归一分    0.836000
专业乐迷_归一分    0.690000
大众乐迷_归一分    0.779444
总得分_归一分     0.778734

可以看到是专业乐迷,所以李红旗啊,如果专业乐迷们说什么喜欢你们,你们千万不要相信。

最后,我要来预测今晚谁是这个夏天的Hot5,感谢你坚持看到这里!

预测方式很简单,将归一分和标准分均排名前五的乐队,拉出来看一下:

total_nor_score_t.groupby('乐队').mean().sort_values(by = '总得分_归一分',ascending = False).head(9)
total_score_mean.sort_values(by = '总得分_标准分',ascending= False).head(9)
# 取前五的交集
hot5_nor = total_nor_score_t.groupby('乐队').mean().sort_values(by = '总得分_归一分',ascending = False).head(5).index
hot5_z = total_score_mean.sort_values(by = '总得分_标准分',ascending= False).head(5).index
set(hot5_nor) & set(hot5_z)
{'九连真人', '刺猬', '新裤子', '痛痒乐队'}

结果只有4只乐队是重合的,剩余的三只乐队中,旅行团在归一分排序中在盘尼西林前面,而标准分落后,Click#15两种计算方式结果均在最后。因此,第五名的悬念应该是在旅行团乐队和盘尼西林之间,至于最后是谁,就让今晚拭目以待吧!

写在最后,因为这是我的第一篇推文,以后还会写更多数据分析方面的,以及一些读书笔记,Python学习笔记,还有美剧推荐,哲学,历史,音乐等。之所以起名为猪栏守望者,灵感来自麦田守望者,是因为希望能够给大家一些不一样的东西,一些经过独立思考和分析的东西,让资讯不全是低级的消遣娱乐。喜欢记得点在看关注

点击阅读原文可以前往github获取完整分析代码

原文发布于微信公众号 - 智能工场AIWorkshop(qddata)

原文发表时间:2019-08-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券