python爬取電競《絕地求生》比賽數據集分析


      python爬取電競《絕地求生》比賽數據集分析

一,選題背景

  電子競技(Electronic Sports)是電子游戲比賽達到“競技”層面的體育項目。電子競技就是利用電子設備作為運動器械進行的、人與人之間的智力和體力結合的比拼。通過電子競技,可以鍛煉和提高參與者的思維能力、反應能力、四肢協調能力和意志力,培養團隊精神,並且職業電競對體力也有較高要求。電子競技也是一種職業,和棋藝等非電子游戲比賽類似,2003年11月18日,國家體育局正式批准,將電子競技列為第99個正式體育競賽項目。2008年,國家體育總局將電子競技改批為第78號正式體育競賽項目。2018年雅加達亞運會將電子競技納為表演項目。數據來源:20G絕地求生比賽數據集。

 

二,設計方案

1,爬蟲名稱:python爬取電競《絕地求生》比賽數據集分析

2,爬蟲爬取的內容與數據特征分析

  主要分成兩部分,一部分是玩家比賽的統計數據,以agg_match_stats開頭,一部分是玩家被擊殺的數據,以kill_match_stats開頭本次分析選取其中的兩個數據集進行分析

3,設計方案:

  1. 飛機嗡嗡地,我到底跳哪里比較安全?

  2. 我是該苟着不動,還是應該出去猛干?

  3. 是該單打獨斗還是跟隊友一起配合?

  4. 毒來了我跑不過毒怎么辦啊?

  5. 什么武器最有用?

  6. 近戰適合使用什么武器,狙擊適合使用什么武器呢?

  7. 最后的毒圈一般會在哪里呢?

 

三,結果特征分析

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庫做出游戲中的熱感應圖,是本次程序設計最大的收獲,已經達到預期目標對絕地求生比賽數據集分析和可視化。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM