python爬取电竞《绝地求生》比赛数据集分析
python爬取电竞《绝地求生》比赛数据集分析
一,选题背景
电子竞技(Electronic Sports)是电子游戏比赛达到“竞技”层面的体育项目。电子竞技就是利用电子设备作为运动器械进行的、人与人之间的智力和体力结合的比拼。通过电子竞技,可以锻炼和提高参与者的思维能力、反应能力、四肢协调能力和意志力,培养团队精神,并且职业电竞对体力也有较高要求。电子竞技也是一种职业,和棋艺等非电子游戏比赛类似,2003年11月18日,国家体育局正式批准,将电子竞技列为第99个正式体育竞赛项目。2008年,国家体育总局将电子竞技改批为第78号正式体育竞赛项目。2018年雅加达亚运会将电子竞技纳为表演项目。数据来源:20G绝地求生比赛数据集。
二,设计方案
1,爬虫名称:python爬取电竞《绝地求生》比赛数据集分析
2,爬虫爬取的内容与数据特征分析
主要分成两部分,一部分是玩家比赛的统计数据,以agg_match_stats开头,一部分是玩家被击杀的数据,以kill_match_stats开头本次分析选取其中的两个数据集进行分析
3,设计方案:
-
飞机嗡嗡地,我到底跳哪里比较安全?
-
我是该苟着不动,还是应该出去猛干?
-
是该单打独斗还是跟队友一起配合?
-
毒来了我跑不过毒怎么办啊?
-
什么武器最有用?
-
近战适合使用什么武器,狙击适合使用什么武器呢?
-
最后的毒圈一般会在哪里呢?
三,结果特征分析
1,页面的结构与特征分析
四,程序设计
1,# 使用pandas读取数据
1 import pandas as pd 2 import numpy as np 3 import matplotlib.pyplot as plt 4 import seaborn as sns 5 %matplotlib inline 6 plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体 7 plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题 8 9 # 使用pandas读取数据 10 agg1 = pd.read_csv('/Users/apple/Desktop/pubg/aggregate/agg_match_stats_1.csv')
2,# 探索数据结构并数据清洗
1 agg1.head()
# 总共有13844275行玩家数据,15列
1 agg1.shape
1 agg1.columns
1 agg1.info()
3,数据分析与可视化
# 丢弃重复数据
1 agg1.drop_duplicates(inplace=True) 2 3 agg1.loc[1]
# 添加是否成功吃鸡列
1 agg1['won'] = agg1['team_placement'] == 1
# 添加是否搭乘过车辆列
1 agg1['drove'] = agg1['player_dist_ride'] != 0
我是该苟着不动,还是应该出去猛干
1 agg1.loc[agg1['player_kills'] < 40, ['player_kills', 'won']].groupby('player_kills').won.mean().plot.bar(figsize=(15,6), rot=0) 2 plt.xlabel('击杀人数', fontsize=14) 3 plt.ylabel("吃鸡概率", fontsize=14) 4 plt.title('击杀人数与吃鸡概率的关系', fontsize=14)
不同模式下的平均击杀人数:
1 agg1.groupby('party_size').player_kills.mean()
1 g = sns.FacetGrid(agg1.loc[agg1['player_kills']<=10, ['party_size', 'player_kills']], row="party_size", size=4, aspect=2) 2 g = g.map(sns.countplot, "player_kills") 3 4 5 6 party_size=1
1 party_size=2
1 party_size=4
是该单打独斗还是跟队友一起配合?
1 agg1.loc[agg1['party_size']!=1, ['player_assists', 'won']].groupby('player_assists').won.mean().plot.bar(figsize=(15,6), rot=0) 2 plt.xlabel('助攻次数', fontsize=14) 3 plt.ylabel("吃鸡概率", fontsize=14) 4 plt.title('助攻次数与吃鸡概率的关系', fontsize=14)
“毒来了我跑不过毒怎么办啊”之车辆到底有多重要?
1 agg1.groupby('drove').won.mean().plot.barh(figsize=(6,3)) 2 plt.xlabel("吃鸡概率", fontsize=14) 3 plt.ylabel("是否搭乘过车辆", fontsize=14) 4 plt.title('搭乘车辆与吃鸡概率的关系', fontsize=14) 5 plt.yticks([1,0],['是','否'])
1 dist_ride = agg1.loc[agg1['player_dist_ride']<12000, ['player_dist_ride', 'won']] 2 3 labels=["0-1k", "1-2k", "2-3k", "3-4k","4-5k", "5-6k", "6-7k", "7-8k", "8-9k", "9-10k", "10-11k", "11-12k"] 4 dist_ride['drove_cut'] = pd.cut(dist_ride['player_dist_ride'], 12, labels=labels) 5 6 dist_ride.groupby('drove_cut').won.mean().plot.bar(rot=60, figsize=(8,4)) 7 plt.xlabel("搭乘车辆里程", fontsize=14) 8 plt.ylabel("吃鸡概率", fontsize=14) 9 plt.title('搭乘车辆里程与吃鸡概率的关系', fontsize=14)
match_unique = agg1.loc[agg1['party_size'] == 1, 'match_id'].unique()
match_unique = agg1.loc[agg1['party_size'] == 1, 'match_id'].unique()
把玩家被击杀的数据导入进来
1 # 先把玩家被击杀的数据导入进来并探索数据 2 death1 = pd.read_csv('/Users/apple/Desktop/pubg/deaths/kill_match_stats_final_1.csv') 3 4 death1.head()
1 death1.info() 2 3 death1.shape 4 5 death1_solo = death1[death1['match_id'].isin(match_unique)] 6 7 death1_solo.info()
飞机嗡嗡地,我到底跳哪里比较安全
1 # 只统计单人模式,筛选存活不超过180秒的玩家数据 2 death_180_seconds_erg = death1_solo.loc[(death1_solo['map'] == 'ERANGEL')&(death1_solo['time'] < 180)&(death1_solo['victim_position_x']>0), :].dropna() 3 death_180_seconds_mrm = death1_solo.loc[(death1_solo['map'] == 'MIRAMAR')&(death1_solo['time'] < 180)&(death1_solo['victim_position_x']>0), :].dropna() 4 5 death_180_seconds_erg.shape 6 7 death_180_seconds_mrm.shape
1 # 选择存活不过180秒的玩家死亡位置 2 data_erg = death_180_seconds_erg[['victim_position_x', 'victim_position_y']].values 3 data_mrm = death_180_seconds_mrm[['victim_position_x', 'victim_position_y']].values 4 5 # 重新scale玩家位置 6 data_erg = data_erg*4096/800000 7 data_mrm = data_mrm*1000/800000 8 9 from scipy.ndimage.filters import gaussian_filter 10 import matplotlib.cm as cm 11 from matplotlib.colors import Normalize 12 from scipy.misc.pilutil import imread 13 14 from scipy.ndimage.filters import gaussian_filter 15 import matplotlib.cm as cm 16 from matplotlib.colors import Normalize 17 18 def heatmap(x, y, s, bins=100): 19 heatmap, xedges, yedges = np.histogram2d(x, y, bins=bins) 20 heatmap = gaussian_filter(heatmap, sigma=s) 21 22 extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]] 23 return heatmap.T, extent 24 25 bg = imread('/Users/apple/Desktop/pubg/erangel.jpg') 26 hmap, extent = heatmap(data_erg[:,0], data_erg[:,1], 4.5) 27 alphas = np.clip(Normalize(0, hmap.max(), clip=True)(hmap)*4.5, 0.0, 1.) 28 colors = Normalize(0, hmap.max(), clip=True)(hmap) 29 colors = cm.Reds(colors) 30 colors[..., -1] = alphas 31 32 fig, ax = plt.subplots(figsize=(24,24)) 33 ax.set_xlim(0, 4096); ax.set_ylim(0, 4096) 34 ax.imshow(bg) 35 ax.imshow(colors, extent=extent, origin='lower', cmap=cm.Reds, alpha=0.9) 36 plt.gca().invert_yaxis()
1 bg = imread('/Users/apple/Desktop/pubg/miramar.jpg') 2 hmap, extent = heatmap(data_mrm[:,0], data_mrm[:,1], 4) 3 alphas = np.clip(Normalize(0, hmap.max(), clip=True)(hmap)*4, 0.0, 1.) 4 colors = Normalize(0, hmap.max(), clip=True)(hmap) 5 colors = cm.Reds(colors) 6 colors[..., -1] = alphas 7 8 fig, ax = plt.subplots(figsize=(24,24)) 9 ax.set_xlim(0, 1000); ax.set_ylim(0, 1000) 10 ax.imshow(bg) 11 ax.imshow(colors, extent=extent, origin='lower', cmap=cm.Reds, alpha=0.9) 12 #plt.scatter(plot_data_mr[:,0], plot_data_mr[:,1]) 13 plt.gca().invert_yaxis()
最后的毒圈一般会在哪里呢?
这里选取每场比赛第一名和第二名的位置数据,因为第一名和第二名所在的位置基本上就是最后的毒圈所在的位置
1 death_final_circle_erg = death1_solo.loc[(death1_solo['map'] == 'ERANGEL')&(death1_solo['victim_placement'] == 2)&(death1_solo['victim_position_x']>0)&(death1_solo['killer_position_x']>0), :].dropna() 2 death_final_circle_mrm = death1_solo.loc[(death1_solo['map'] == 'MIRAMAR')&(death1_solo['victim_placement'] == 2)&(death1_solo['victim_position_x']>0)&(death1_solo['killer_position_x']>0), :].dropna() 3 4 print(death_final_circle_erg.shape) 5 print(death_final_circle_mrm.shape) 6 7 final_circle_erg = np.vstack([death_final_circle_erg[['victim_position_x', 'victim_position_y']].values, 8 death_final_circle_erg[['killer_position_x', 'killer_position_y']].values])*4096/800000 9 final_circle_mrm = np.vstack([death_final_circle_mrm[['victim_position_x', 'victim_position_y']].values, 10 death_final_circle_mrm[['killer_position_x', 'killer_position_y']].values])*1000/800000
1 bg = imread('/Users/apple/Desktop/pubg/erangel.jpg') 2 hmap, extent = heatmap(final_circle_erg[:,0], final_circle_erg[:,1], 1.5) 3 alphas = np.clip(Normalize(0, hmap.max(), clip=True)(hmap)*1.5, 0.0, 1.) 4 colors = Normalize(0, hmap.max(), clip=True)(hmap) 5 colors = cm.Reds(colors) 6 colors[..., -1] = alphas 7 8 fig, ax = plt.subplots(figsize=(24,24)) 9 ax.set_xlim(0, 4096); ax.set_ylim(0, 4096) 10 ax.imshow(bg) 11 ax.imshow(colors, extent=extent, origin='lower', cmap=cm.Reds, alpha=0.9) 12 #plt.scatter(plot_data_er[:,0], plot_data_er[:,1]) 13 14 plt.gca().invert_yaxis()
1 bg = imread('/Users/apple/Desktop/pubg/miramar.jpg') 2 hmap, extent = heatmap(final_circle_mrm[:,0], final_circle_mrm[:,1], 1.5) 3 alphas = np.clip(Normalize(0, hmap.max(), clip=True)(hmap)*1.5, 0.0, 1.) 4 colors = Normalize(0, hmap.max(), clip=True)(hmap) 5 colors = cm.Reds(colors) 6 colors[..., -1] = alphas 7 8 fig, ax = plt.subplots(figsize=(24,24)) 9 ax.set_xlim(0, 1000); ax.set_ylim(0, 1000) 10 ax.imshow(bg) 11 ax.imshow(colors, extent=extent, origin='lower', cmap=cm.Reds, alpha=0.9) 12 #plt.scatter(plot_data_mr[:,0], plot_data_mr[:,1]) 13 plt.gca().invert_yaxis()
什么武器最有用?
1 erg_died_of = death1.loc[(death1['map']=='ERANGEL')&(death1['killer_position_x']>0)&(death1['victim_position_x']>0)&(death1['killed_by']!='Down and Out'),:] 2 mrm_died_of = death1.loc[(death1['map']=='MIRAMAR')&(death1['killer_position_x']>0)&(death1['victim_position_x']>0)&(death1['killed_by']!='Down and Out'),:] 3 4 print(erg_died_of.shape) 5 print(mrm_died_of.shape)
1 erg_died_of['killed_by'].value_counts()[:10].plot.barh(figsize=(10,5)) 2 plt.xlabel("被击杀人数", fontsize=14) 3 plt.ylabel("击杀的武器", fontsize=14) 4 plt.title('武器跟击杀人数的统计(绝地海岛艾伦格)', fontsize=14) 5 plt.yticks(fontsize=12)
狙击适合使用什么武器?
1 # 把位置信息转换成距离,以“米”为单位 2 erg_distance = np.sqrt(((erg_died_of['killer_position_x']-erg_died_of['victim_position_x'])/100)**2 + ((erg_died_of['killer_position_y']-erg_died_of['victim_position_y'])/100)**2) 3 4 5 6 mrm_distance = np.sqrt(((mrm_died_of['killer_position_x']-mrm_died_of['victim_position_x'])/100)**2 + ((mrm_died_of['killer_position_y']-mrm_died_of['victim_position_y'])/100)**2) 7 8 9 10 sns.distplot(erg_distance.loc[erg_distance<400])
1 erg_died_of.loc[(erg_distance > 800)&(erg_distance < 1500), 'killed_by'].value_counts()[:10].plot.bar(rot=30) 2 plt.xlabel("狙击的武器", fontsize=14) 3 plt.ylabel("被狙击的人数", fontsize=14) 4 plt.title('狙击武器跟击杀人数的统计(绝地海岛艾伦格)', fontsize=14) 5 plt.yticks(fontsize=12)
1 mrm_died_of.loc[(mrm_distance > 800)&(mrm_distance < 1000), 'killed_by'].value_counts()[:10].plot.bar(rot=30) 2 plt.xlabel("狙击的武器", fontsize=14) 3 plt.ylabel("被狙击的人数", fontsize=14) 4 plt.title('狙击武器跟击杀人数的统计(热情沙漠米拉玛)', fontsize=14) 5 plt.yticks(fontsize=12)
近战适合使用什么武器?
1 erg_died_of.loc[erg_distance<10, 'killed_by'].value_counts()[:10].plot.bar(rot=30) 2 plt.xlabel("近战武器", fontsize=14) 3 plt.ylabel("被击杀的人数", fontsize=14) 4 plt.title('近战武器跟击杀人数的统计(绝地海岛艾伦格)', fontsize=14) 5 plt.yticks(fontsize=12)
1 mrm_died_of.loc[mrm_distance<10, 'killed_by'].value_counts()[:10].plot.bar(rot=30) 2 plt.xlabel("近战武器", fontsize=14) 3 plt.ylabel("被击杀的人数", fontsize=14) 4 plt.title('近战武器武器跟击杀人数的统计(热情沙漠米拉玛)', fontsize=14) 5 plt.yticks(fontsize=12)
Top10武器在各距离下的击杀百分比
1 erg_died_of['erg_dist'] = erg_distance 2 erg_died_of = erg_died_of.loc[erg_died_of['erg_dist']<800, :] 3 top_weapons_erg = list(erg_died_of['killed_by'].value_counts()[:10].index) 4 top_weapon_kills = erg_died_of[np.in1d(erg_died_of['killed_by'], top_weapons_erg)].copy() 5 top_weapon_kills['bin'] = pd.cut(top_weapon_kills['erg_dist'], np.arange(0, 800, 10), include_lowest=True, labels=False) 6 top_weapon_kills_wide = top_weapon_kills.groupby(['killed_by', 'bin']).size().unstack(fill_value=0).transpose() 7 8 9 10 top_weapon_kills_wide = top_weapon_kills_wide.div(top_weapon_kills_wide.sum(axis=1), axis=0) 11 12 13 14 from bokeh.models.tools import HoverTool 15 from bokeh.palettes import brewer 16 from bokeh.plotting import figure, show, output_notebook 17 from bokeh.models.sources import ColumnDataSource 18 19 def stacked(df): 20 df_top = df.cumsum(axis=1) 21 df_bottom = df_top.shift(axis=1).fillna(0)[::-1] 22 df_stack = pd.concat([df_bottom, df_top], ignore_index=True) 23 return df_stack 24 25 hover = HoverTool( 26 tooltips=[ 27 ("index", "$index"), 28 ("weapon", "@weapon"), 29 ("(x,y)", "($x, $y)") 30 ], 31 point_policy='follow_mouse' 32 ) 33 34 areas = stacked(top_weapon_kills_wide) 35 36 colors = brewer['Spectral'][areas.shape[1]] 37 x2 = np.hstack((top_weapon_kills_wide.index[::-1], 38 top_weapon_kills_wide.index)) /0.095 39 40 TOOLS="pan,wheel_zoom,box_zoom,reset,previewsave" 41 output_notebook() 42 p = figure(x_range=(1, 800), y_range=(0, 1), tools=[TOOLS, hover], plot_width=800) 43 p.grid.minor_grid_line_color = '#eeeeee' 44 45 source = ColumnDataSource(data={ 46 'x': [x2] * areas.shape[1], 47 'y': [areas[c].values for c in areas], 48 'weapon': list(top_weapon_kills_wide.columns), 49 'color': colors 50 }) 51 52 p.patches('x', 'y', source=source, legend="weapon", 53 color='color', alpha=0.8, line_color=None) 54 p.title.text = "Top10武器在各距离下的击杀百分比(绝地海岛艾伦格)" 55 p.xaxis.axis_label = "击杀距离(0-800米)" 56 p.yaxis.axis_label = "百分比" 57 58 show(p) 59 60 61 62 mrm_died_of['erg_dist'] = mrm_distance 63 mrm_died_of = mrm_died_of.loc[mrm_died_of['erg_dist']<800, :] 64 top_weapons_erg = list(mrm_died_of['killed_by'].value_counts()[:10].index) 65 top_weapon_kills = mrm_died_of[np.in1d(mrm_died_of['killed_by'], top_weapons_erg)].copy() 66 top_weapon_kills['bin'] = pd.cut(top_weapon_kills['erg_dist'], np.arange(0, 800, 10), include_lowest=True, labels=False) 67 top_weapon_kills_wide = top_weapon_kills.groupby(['killed_by', 'bin']).size().unstack(fill_value=0).transpose() 68 69 top_weapon_kills_wide = top_weapon_kills_wide.div(top_weapon_kills_wide.sum(axis=1), axis=0) 70 71 72 73 def stacked(df): 74 df_top = df.cumsum(axis=1) 75 df_bottom = df_top.shift(axis=1).fillna(0)[::-1] 76 df_stack = pd.concat([df_bottom, df_top], ignore_index=True) 77 return df_stack 78 79 hover = HoverTool( 80 tooltips=[ 81 ("index", "$index"), 82 ("weapon", "@weapon"), 83 ("(x,y)", "($x, $y)") 84 ], 85 point_policy='follow_mouse' 86 ) 87 88 areas = stacked(top_weapon_kills_wide) 89 90 colors = brewer['Spectral'][areas.shape[1]] 91 x2 = np.hstack((top_weapon_kills_wide.index[::-1], 92 top_weapon_kills_wide.index)) /0.095 93 94 TOOLS="pan,wheel_zoom,box_zoom,reset,previewsave" 95 output_notebook() 96 p = figure(x_range=(1, 800), y_range=(0, 1), tools=[TOOLS, hover], plot_width=800) 97 p.grid.minor_grid_line_color = '#eeeeee' 98 99 source = ColumnDataSource(data={ 100 'x': [x2] * areas.shape[1], 101 'y': [areas[c].values for c in areas], 102 'weapon': list(top_weapon_kills_wide.columns), 103 'color': colors 104 }) 105 106 p.patches('x', 'y', source=source, legend="weapon", 107 color='color', alpha=0.8, line_color=None) 108 p.title.text = "Top10武器在各距离下的击杀百分比(热情沙漠米拉玛)" 109 p.xaxis.axis_label = "击杀距离(0-800米)" 110 p.yaxis.axis_label = "击杀百分比" 111 112 show(p)
自己把自己干倒的方式与人数
1 death1.head()
1 kill_by_self = death1.loc[death1['killer_name']==death1['victim_name'], "killed_by"] 2 3 kill_by_self.value_counts()[:10].plot.barh() 4 plt.xlabel("自毙的人数", fontsize=14) 5 plt.ylabel("自毙的方式", fontsize=14) 6 plt.title('自己把自己干倒的方式与人数', fontsize=14) 7 plt.yticks(fontsize=12)
1 # 自己把自己干倒的人数场均百分比 2 kill_by_self.shape[0]/death1.shape[0]*100
完整代码:
1 import pandas as pd 2 import numpy as np 3 import matplotlib.pyplot as plt 4 import seaborn as sns 5 %matplotlib inline 6 plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体 7 plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题 8 9 # 使用pandas读取数据 10 agg1 = pd.read_csv('/Users/apple/Desktop/pubg/aggregate/agg_match_stats_1.csv') 11 12 # 探索数据结构 13 agg1.head() 14 15 # 总共有13844275行玩家数据,15列 16 agg1.shape 17 18 agg1.columns 19 20 agg1.info() 21 22 # 丢弃重复数据 23 agg1.drop_duplicates(inplace=True) 24 25 agg1.loc[1] 26 27 # 添加是否成功吃鸡列 28 agg1['won'] = agg1['team_placement'] == 1 29 30 # 添加是否搭乘过车辆列 31 agg1['drove'] = agg1['player_dist_ride'] != 0 32 33 agg1.loc[agg1['player_kills'] < 40, ['player_kills', 'won']].groupby('player_kills').won.mean().plot.bar(figsize=(15,6), rot=0) 34 plt.xlabel('击杀人数', fontsize=14) 35 plt.ylabel("吃鸡概率", fontsize=14) 36 plt.title('击杀人数与吃鸡概率的关系', fontsize=14) 37 38 agg1.groupby('party_size').player_kills.mean() 39 40 g = sns.FacetGrid(agg1.loc[agg1['player_kills']<=10, ['party_size', 'player_kills']], row="party_size", size=4, aspect=2) 41 g = g.map(sns.countplot, "player_kills") 42 43 agg1.loc[agg1['party_size']!=1, ['player_assists', 'won']].groupby('player_assists').won.mean().plot.bar(figsize=(15,6), rot=0) 44 plt.xlabel('助攻次数', fontsize=14) 45 plt.ylabel("吃鸡概率", fontsize=14) 46 plt.title('助攻次数与吃鸡概率的关系', fontsize=14) 47 48 agg1.groupby('drove').won.mean().plot.barh(figsize=(6,3)) 49 plt.xlabel("吃鸡概率", fontsize=14) 50 plt.ylabel("是否搭乘过车辆", fontsize=14) 51 plt.title('搭乘车辆与吃鸡概率的关系', fontsize=14) 52 plt.yticks([1,0],['是','否']) 53 54 dist_ride = agg1.loc[agg1['player_dist_ride']<12000, ['player_dist_ride', 'won']] 55 56 labels=["0-1k", "1-2k", "2-3k", "3-4k","4-5k", "5-6k", "6-7k", "7-8k", "8-9k", "9-10k", "10-11k", "11-12k"] 57 dist_ride['drove_cut'] = pd.cut(dist_ride['player_dist_ride'], 12, labels=labels) 58 59 dist_ride.groupby('drove_cut').won.mean().plot.bar(rot=60, figsize=(8,4)) 60 plt.xlabel("搭乘车辆里程", fontsize=14) 61 plt.ylabel("吃鸡概率", fontsize=14) 62 plt.title('搭乘车辆里程与吃鸡概率的关系', fontsize=14) 63 64 match_unique = agg1.loc[agg1['party_size'] == 1, 'match_id'].unique() 65 66 # 先把玩家被击杀的数据导入进来并探索数据 67 death1 = pd.read_csv('/Users/apple/Desktop/pubg/deaths/kill_match_stats_final_1.csv') 68 69 death1.head() 70 71 death1.info() 72 73 death1.shape 74 75 death1_solo = death1[death1['match_id'].isin(match_unique)] 76 77 death1_solo.info() 78 79 # 只统计单人模式,筛选存活不超过180秒的玩家数据 80 death_180_seconds_erg = death1_solo.loc[(death1_solo['map'] == 'ERANGEL')&(death1_solo['time'] < 180)&(death1_solo['victim_position_x']>0), :].dropna() 81 death_180_seconds_mrm = death1_solo.loc[(death1_solo['map'] == 'MIRAMAR')&(death1_solo['time'] < 180)&(death1_solo['victim_position_x']>0), :].dropna() 82 83 death_180_seconds_erg.shape 84 85 death_180_seconds_mrm.shape 86 87 # 选择存活不过180秒的玩家死亡位置 88 data_erg = death_180_seconds_erg[['victim_position_x', 'victim_position_y']].values 89 data_mrm = death_180_seconds_mrm[['victim_position_x', 'victim_position_y']].values 90 91 # 重新scale玩家位置 92 data_erg = data_erg*4096/800000 93 data_mrm = data_mrm*1000/800000 94 95 from scipy.ndimage.filters import gaussian_filter 96 import matplotlib.cm as cm 97 from matplotlib.colors import Normalize 98 from scipy.misc.pilutil import imread 99 100 from scipy.ndimage.filters import gaussian_filter 101 import matplotlib.cm as cm 102 from matplotlib.colors import Normalize 103 104 def heatmap(x, y, s, bins=100): 105 heatmap, xedges, yedges = np.histogram2d(x, y, bins=bins) 106 heatmap = gaussian_filter(heatmap, sigma=s) 107 108 extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]] 109 return heatmap.T, extent 110 111 bg = imread('/Users/apple/Desktop/pubg/erangel.jpg') 112 hmap, extent = heatmap(data_erg[:,0], data_erg[:,1], 4.5) 113 alphas = np.clip(Normalize(0, hmap.max(), clip=True)(hmap)*4.5, 0.0, 1.) 114 colors = Normalize(0, hmap.max(), clip=True)(hmap) 115 colors = cm.Reds(colors) 116 colors[..., -1] = alphas 117 118 fig, ax = plt.subplots(figsize=(24,24)) 119 ax.set_xlim(0, 4096); ax.set_ylim(0, 4096) 120 ax.imshow(bg) 121 ax.imshow(colors, extent=extent, origin='lower', cmap=cm.Reds, alpha=0.9) 122 plt.gca().invert_yaxis() 123 124 bg = imread('/Users/apple/Desktop/pubg/miramar.jpg') 125 hmap, extent = heatmap(data_mrm[:,0], data_mrm[:,1], 4) 126 alphas = np.clip(Normalize(0, hmap.max(), clip=True)(hmap)*4, 0.0, 1.) 127 colors = Normalize(0, hmap.max(), clip=True)(hmap) 128 colors = cm.Reds(colors) 129 colors[..., -1] = alphas 130 131 fig, ax = plt.subplots(figsize=(24,24)) 132 ax.set_xlim(0, 1000); ax.set_ylim(0, 1000) 133 ax.imshow(bg) 134 ax.imshow(colors, extent=extent, origin='lower', cmap=cm.Reds, alpha=0.9) 135 #plt.scatter(plot_data_mr[:,0], plot_data_mr[:,1]) 136 plt.gca().invert_yaxis() 137 138 death_final_circle_erg = death1_solo.loc[(death1_solo['map'] == 'ERANGEL')&(death1_solo['victim_placement'] == 2)&(death1_solo['victim_position_x']>0)&(death1_solo['killer_position_x']>0), :].dropna() 139 death_final_circle_mrm = death1_solo.loc[(death1_solo['map'] == 'MIRAMAR')&(death1_solo['victim_placement'] == 2)&(death1_solo['victim_position_x']>0)&(death1_solo['killer_position_x']>0), :].dropna() 140 141 print(death_final_circle_erg.shape) 142 print(death_final_circle_mrm.shape) 143 144 final_circle_erg = np.vstack([death_final_circle_erg[['victim_position_x', 'victim_position_y']].values, 145 death_final_circle_erg[['killer_position_x', 'killer_position_y']].values])*4096/800000 146 final_circle_mrm = np.vstack([death_final_circle_mrm[['victim_position_x', 'victim_position_y']].values, 147 death_final_circle_mrm[['killer_position_x', 'killer_position_y']].values])*1000/800000 148 149 bg = imread('/Users/apple/Desktop/pubg/erangel.jpg') 150 hmap, extent = heatmap(final_circle_erg[:,0], final_circle_erg[:,1], 1.5) 151 alphas = np.clip(Normalize(0, hmap.max(), clip=True)(hmap)*1.5, 0.0, 1.) 152 colors = Normalize(0, hmap.max(), clip=True)(hmap) 153 colors = cm.Reds(colors) 154 colors[..., -1] = alphas 155 156 fig, ax = plt.subplots(figsize=(24,24)) 157 ax.set_xlim(0, 4096); ax.set_ylim(0, 4096) 158 ax.imshow(bg) 159 ax.imshow(colors, extent=extent, origin='lower', cmap=cm.Reds, alpha=0.9) 160 #plt.scatter(plot_data_er[:,0], plot_data_er[:,1]) 161 plt.gca().invert_yaxis() 162 163 bg = imread('/Users/apple/Desktop/pubg/miramar.jpg') 164 hmap, extent = heatmap(final_circle_mrm[:,0], final_circle_mrm[:,1], 1.5) 165 alphas = np.clip(Normalize(0, hmap.max(), clip=True)(hmap)*1.5, 0.0, 1.) 166 colors = Normalize(0, hmap.max(), clip=True)(hmap) 167 colors = cm.Reds(colors) 168 colors[..., -1] = alphas 169 170 fig, ax = plt.subplots(figsize=(24,24)) 171 ax.set_xlim(0, 1000); ax.set_ylim(0, 1000) 172 ax.imshow(bg) 173 ax.imshow(colors, extent=extent, origin='lower', cmap=cm.Reds, alpha=0.9) 174 #plt.scatter(plot_data_mr[:,0], plot_data_mr[:,1]) 175 plt.gca().invert_yaxis() 176 177 erg_died_of = death1.loc[(death1['map']=='ERANGEL')&(death1['killer_position_x']>0)&(death1['victim_position_x']>0)&(death1['killed_by']!='Down and Out'),:] 178 mrm_died_of = death1.loc[(death1['map']=='MIRAMAR')&(death1['killer_position_x']>0)&(death1['victim_position_x']>0)&(death1['killed_by']!='Down and Out'),:] 179 180 print(erg_died_of.shape) 181 print(mrm_died_of.shape) 182 183 erg_died_of['killed_by'].value_counts()[:10].plot.barh(figsize=(10,5)) 184 plt.xlabel("被击杀人数", fontsize=14) 185 plt.ylabel("击杀的武器", fontsize=14) 186 plt.title('武器跟击杀人数的统计(绝地海岛艾伦格)', fontsize=14) 187 plt.yticks(fontsize=12) 188 189 mrm_died_of['killed_by'].value_counts()[:10].plot.barh(figsize=(10,5)) 190 plt.xlabel("被击杀人数", fontsize=14) 191 plt.ylabel("击杀的武器", fontsize=14) 192 plt.title('武器跟击杀人数的统计(热情沙漠米拉玛)', fontsize=14) 193 plt.yticks(fontsize=12) 194 195 # 把位置信息转换成距离,以“米”为单位 196 erg_distance = np.sqrt(((erg_died_of['killer_position_x']-erg_died_of['victim_position_x'])/100)**2 + ((erg_died_of['killer_position_y']-erg_died_of['victim_position_y'])/100)**2) 197 198 mrm_distance = np.sqrt(((mrm_died_of['killer_position_x']-mrm_died_of['victim_position_x'])/100)**2 + ((mrm_died_of['killer_position_y']-mrm_died_of['victim_position_y'])/100)**2) 199 200 sns.distplot(erg_distance.loc[erg_distance<400]) 201 202 erg_died_of.loc[(erg_distance > 800)&(erg_distance < 1500), 'killed_by'].value_counts()[:10].plot.bar(rot=30) 203 plt.xlabel("狙击的武器", fontsize=14) 204 plt.ylabel("被狙击的人数", fontsize=14) 205 plt.title('狙击武器跟击杀人数的统计(绝地海岛艾伦格)', fontsize=14) 206 plt.yticks(fontsize=12) 207 208 mrm_died_of.loc[(mrm_distance > 800)&(mrm_distance < 1000), 'killed_by'].value_counts()[:10].plot.bar(rot=30) 209 plt.xlabel("狙击的武器", fontsize=14) 210 plt.ylabel("被狙击的人数", fontsize=14) 211 plt.title('狙击武器跟击杀人数的统计(热情沙漠米拉玛)', fontsize=14) 212 plt.yticks(fontsize=12) 213 214 erg_died_of.loc[erg_distance<10, 'killed_by'].value_counts()[:10].plot.bar(rot=30) 215 plt.xlabel("近战武器", fontsize=14) 216 plt.ylabel("被击杀的人数", fontsize=14) 217 plt.title('近战武器跟击杀人数的统计(绝地海岛艾伦格)', fontsize=14) 218 plt.yticks(fontsize=12) 219 220 mrm_died_of.loc[mrm_distance<10, 'killed_by'].value_counts()[:10].plot.bar(rot=30) 221 plt.xlabel("近战武器", fontsize=14) 222 plt.ylabel("被击杀的人数", fontsize=14) 223 plt.title('近战武器武器跟击杀人数的统计(热情沙漠米拉玛)', fontsize=14) 224 plt.yticks(fontsize=12) 225 226 erg_died_of['erg_dist'] = erg_distance 227 erg_died_of = erg_died_of.loc[erg_died_of['erg_dist']<800, :] 228 top_weapons_erg = list(erg_died_of['killed_by'].value_counts()[:10].index) 229 top_weapon_kills = erg_died_of[np.in1d(erg_died_of['killed_by'], top_weapons_erg)].copy() 230 top_weapon_kills['bin'] = pd.cut(top_weapon_kills['erg_dist'], np.arange(0, 800, 10), include_lowest=True, labels=False) 231 top_weapon_kills_wide = top_weapon_kills.groupby(['killed_by', 'bin']).size().unstack(fill_value=0).transpose() 232 233 top_weapon_kills_wide = top_weapon_kills_wide.div(top_weapon_kills_wide.sum(axis=1), axis=0) 234 235 from bokeh.models.tools import HoverTool 236 from bokeh.palettes import brewer 237 from bokeh.plotting import figure, show, output_notebook 238 from bokeh.models.sources import ColumnDataSource 239 240 def stacked(df): 241 df_top = df.cumsum(axis=1) 242 df_bottom = df_top.shift(axis=1).fillna(0)[::-1] 243 df_stack = pd.concat([df_bottom, df_top], ignore_index=True) 244 return df_stack 245 246 hover = HoverTool( 247 tooltips=[ 248 ("index", "$index"), 249 ("weapon", "@weapon"), 250 ("(x,y)", "($x, $y)") 251 ], 252 point_policy='follow_mouse' 253 ) 254 255 areas = stacked(top_weapon_kills_wide) 256 257 colors = brewer['Spectral'][areas.shape[1]] 258 x2 = np.hstack((top_weapon_kills_wide.index[::-1], 259 top_weapon_kills_wide.index)) /0.095 260 261 TOOLS="pan,wheel_zoom,box_zoom,reset,previewsave" 262 output_notebook() 263 p = figure(x_range=(1, 800), y_range=(0, 1), tools=[TOOLS, hover], plot_width=800) 264 p.grid.minor_grid_line_color = '#eeeeee' 265 266 source = ColumnDataSource(data={ 267 'x': [x2] * areas.shape[1], 268 'y': [areas[c].values for c in areas], 269 'weapon': list(top_weapon_kills_wide.columns), 270 'color': colors 271 }) 272 273 p.patches('x', 'y', source=source, legend="weapon", 274 color='color', alpha=0.8, line_color=None) 275 p.title.text = "Top10武器在各距离下的击杀百分比(绝地海岛艾伦格)" 276 p.xaxis.axis_label = "击杀距离(0-800米)" 277 p.yaxis.axis_label = "百分比" 278 279 show(p) 280 281 mrm_died_of['erg_dist'] = mrm_distance 282 mrm_died_of = mrm_died_of.loc[mrm_died_of['erg_dist']<800, :] 283 top_weapons_erg = list(mrm_died_of['killed_by'].value_counts()[:10].index) 284 top_weapon_kills = mrm_died_of[np.in1d(mrm_died_of['killed_by'], top_weapons_erg)].copy() 285 top_weapon_kills['bin'] = pd.cut(top_weapon_kills['erg_dist'], np.arange(0, 800, 10), include_lowest=True, labels=False) 286 top_weapon_kills_wide = top_weapon_kills.groupby(['killed_by', 'bin']).size().unstack(fill_value=0).transpose() 287 288 top_weapon_kills_wide = top_weapon_kills_wide.div(top_weapon_kills_wide.sum(axis=1), axis=0) 289 def stacked(df): 290 df_top = df.cumsum(axis=1) 291 df_bottom = df_top.shift(axis=1).fillna(0)[::-1] 292 df_stack = pd.concat([df_bottom, df_top], ignore_index=True) 293 return df_stack 294 295 hover = HoverTool( 296 tooltips=[ 297 ("index", "$index"), 298 ("weapon", "@weapon"), 299 ("(x,y)", "($x, $y)") 300 ], 301 point_policy='follow_mouse' 302 ) 303 304 areas = stacked(top_weapon_kills_wide) 305 306 colors = brewer['Spectral'][areas.shape[1]] 307 x2 = np.hstack((top_weapon_kills_wide.index[::-1], 308 top_weapon_kills_wide.index)) /0.095 309 310 TOOLS="pan,wheel_zoom,box_zoom,reset,previewsave" 311 output_notebook() 312 p = figure(x_range=(1, 800), y_range=(0, 1), tools=[TOOLS, hover], plot_width=800) 313 p.grid.minor_grid_line_color = '#eeeeee' 314 315 source = ColumnDataSource(data={ 316 'x': [x2] * areas.shape[1], 317 'y': [areas[c].values for c in areas], 318 'weapon': list(top_weapon_kills_wide.columns), 319 'color': colors 320 }) 321 322 p.patches('x', 'y', source=source, legend="weapon", 323 color='color', alpha=0.8, line_color=None) 324 p.title.text = "Top10武器在各距离下的击杀百分比(热情沙漠米拉玛)" 325 p.xaxis.axis_label = "击杀距离(0-800米)" 326 p.yaxis.axis_label = "击杀百分比" 327 328 show(p) 329 330 death1.head() 331 332 kill_by_self = death1.loc[death1['killer_name']==death1['victim_name'], "killed_by"] 333 334 kill_by_self.value_counts()[:10].plot.barh() 335 plt.xlabel("自毙的人数", fontsize=14) 336 plt.ylabel("自毙的方式", fontsize=14) 337 plt.title('自己把自己干倒的方式与人数', fontsize=14) 338 plt.yticks(fontsize=12) 339 340 # 自己把自己干倒的人数场均百分比 341 kill_by_self.shape[0]/death1.shape[0]*100
五,总结
使用matplotlib库做出游戏中的热感应图,是本次程序设计最大的收获,已经达到预期目标对绝地求生比赛数据集分析和可视化。