一談起外掛都想不到python程式設計,今天利用Python寫一款吃雞輔助!
那麼我們就用python和R做資料分析來回答以下的靈魂發問?
首先來看下資料:
大吉大利,今晚吃雞~ 今天跟朋友玩了幾把吃雞,經歷了各種死法,還被嘲笑說論女生吃雞的100種死法,比如被拳頭掄死、跳傘落到房頂邊緣摔死 、把吃雞玩成飛車被車技秀死、被隊友用燃燒瓶燒死的。這種遊戲對我來說就是一個讓我明白原來還有這種死法的遊戲。
但是玩歸玩,還是得假裝一下我沉迷學習,所以今天就用吃雞比賽的真實資料來看看如何提高你吃雞的概率。
1、跳哪兒危險?
對於我這樣一直喜歡苟著的良心玩家,在經歷了無數次落地成河的慘痛經歷後,我是堅決不會選擇跳P城這樣樓房密集的城市,窮歸窮但保命要緊。所以我們決定統計一下到底哪些地方更容易落地成河?我們篩選出在前100秒死亡的玩家地點進行視覺化分析。激情沙漠地圖的電站、皮卡多、別墅區、依波城最為危險,火車站、火電廠相對安全。絕地海島中P城、軍事基地、學校、醫院、核電站、防空洞都是絕對的危險地帶。物質豐富的G港居然相對安全。
- 1import numpy as np
- 2import matplotlib.pyplot as plt
- 3import pandas as pd
- 4import seaborn as sns
- 5from scipy.misc.pilutil import imread
- 6import matplotlib.cm as cm
- 7
- 8#匯入部分資料
- 9deaths1 = pd.read_csv("deaths/kill_match_stats_final_0.csv")
- 10deaths2 = pd.read_csv("deaths/kill_match_stats_final_1.csv")
- 11
- 12deaths = pd.concat([deaths1, deaths2])
- 13
- 14#列印前5列,理解變數
- 15print (deaths.head(),' ',len(deaths))
- 16
- 17#兩種地圖
- 18miramar = deaths[deaths["map"] == "MIRAMAR"]
- 19erangel = deaths[deaths["map"] == "ERANGEL"]
- 20
- 21#開局前100秒死亡熱力圖
- 22position_data = ["killer_position_x","killer_position_y","victim_position_x","victim_position_y"]
- 23for position in position_data:
- 24 miramar[position] = miramar[position].apply(lambda x: x*1000/800000)
- 25 miramar = miramar[miramar[position] != 0]
- 26
- 27 erangel[position] = erangel[position].apply(lambda x: x*4096/800000)
- 28 erangel = erangel[erangel[position] != 0]
- 29
- 30n = 50000
- 31mira_sample = miramar[miramar["time"] < 100].sample(n)
- 32eran_sample = erangel[erangel["time"] < 100].sample(n)
- 33
- 34# miramar熱力圖
- 35bg = imread("miramar.jpg")
- 36fig, ax = plt.subplots(1,1,figsize=(15,15))
- 37ax.imshow(bg)
- 38sns.kdeplot(mira_sample["victim_position_x"], mira_sample["victim_position_y"],n_levels=100, cmap=cm.Reds, alpha=0.9)
- 39
- 40# erangel熱力圖
- 41bg = imread("erangel.jpg")
- 42fig, ax = plt.subplots(1,1,figsize=(15,15))
- 43ax.imshow(bg)
- 44sns.kdeplot(eran_sample["victim_position_x"], eran_sample["victim_position_y"], n_levels=100,cmap=cm.Reds, alpha=0.9)
2、苟著還是出去幹?
我到底是苟在房間裡面還是出去和敵人硬拼?這裡因為比賽的規模不一樣,這裡選取參賽人數大於90的比賽資料,然後篩選出團隊team_placement即最後成功吃雞的團隊資料,
1、先計算了吃雞團隊平均擊殺敵人的數量,這裡剔除了四人模式的比賽資料,因為人數太多的團隊會因為數量懸殊平均而變得沒意義;
2、所以我們考慮通過分組統計每一組吃雞中存活到最後的成員擊殺敵人的數量,但是這裡發現數據統計存活時間變數是按照團隊最終存活時間記錄的,所以該想法失敗;
3、最後統計每個吃雞團隊中擊殺人數最多的數量統計,這裡剔除了單人模式的資料,因為單人模式的數量就是每組擊殺最多的數量。最後居然發現還有擊殺數量達到60的,懷疑是否有開掛。想要吃雞還是得出去練槍法,光是苟著是不行的。
- 1library(dplyr)
- 2library(tidyverse)
- 3library(data.table)
- 4library(ggplot2)
- 5pubg_full <- fread("../agg_match_stats.csv")
- 6# 吃雞團隊平均擊殺敵人的數量
- 7attach(pubg_full)
- 8pubg_winner <- pubg_full %>% filter(team_placement==1&party_size<4&game_size>90)
- 9detach(pubg_full)
- 10team_killed <- aggregate(pubg_winner$player_kills, by=list(pubg_winner$match_id,pubg_winner$team_id), FUN="mean")
- 11team_killed$death_num <- ceiling(team_killed$x)
- 12ggplot(data = team_killed) + geom_bar(mapping = aes(x = death_num, y = ..count..), color="steelblue") +
- 13 xlim(0,70) + labs(title = "Number of Death that PUBG Winner team Killed", x="Number of death")
- 14
- 15# 吃雞團隊最後存活的玩家擊殺數量
- 16pubg_winner <- pubg_full %>% filter(pubg_full$team_placement==1) %>% group_by(match_id,team_id)
- 17attach(pubg_winner)
- 18team_leader <- aggregate(player_survive_time~player_kills, data = pubg_winner, FUN="max")
- 19detach(pubg_winner)
- 20
- 21# 吃雞團隊中擊殺敵人最多的數量
- 22pubg_winner <- pubg_full %>% filter(pubg_full$team_placement==1&pubg_full$party_size>1)
- 23attach(pubg_winner)
- 24team_leader <- aggregate(player_kills, by=list(match_id,team_id), FUN="max")
- 25detach(pubg_winner)
- 26ggplot(data = team_leader) + geom_bar(mapping = aes(x = x, y = ..count..), color="steelblue") +
- 27 xlim(0,70) + labs(title = "Number of Death that PUBG Winner Killed", x="Number of death")
3、哪一種武器幹掉的玩家多?
運氣好挑到好武器的時候,你是否猶豫選擇哪一件?從圖上來看,M416和SCAR是不錯的武器,也是相對容易能撿到的武器,大家公認Kar98k是能一槍斃命的好槍,它排名比較靠後的原因也是因為這把槍在比賽比較難得,而且一下擊中敵人也是需要實力的,像我這種撿到98k還裝上8倍鏡但沒捂熱乎1分鐘的玩家是不配得到它的。(捂臉)
- 1#殺人武器排名
- 2death_causes = deaths['killed_by'].value_counts()
- 3
- 4sns.set_context('talk')
- 5fig = plt.figure(figsize=(30, 10))
- 6ax = sns.barplot(x=death_causes.index, y=[v / sum(death_causes) for v in death_causes.values])
- 7ax.set_title('Rate of Death Causes')
- 8ax.set_xticklabels(death_causes.index, rotation=90)
- 9
- 10#排名前20的武器
- 11rank = 20
- 12fig = plt.figure(figsize=(20, 10))
- 13ax = sns.barplot(x=death_causes[:rank].index, y=[v / sum(death_causes) for v in death_causes[:rank].values])
- 14ax.set_title('Rate of Death Causes')
- 15ax.set_xticklabels(death_causes.index, rotation=90)
- 16
- 17#兩個地圖分開取
- 18f, axes = plt.subplots(1, 2, figsize=(30, 10))
- 19axes[0].set_title('Death Causes Rate: Erangel (Top {})'.format(rank))
- 20axes[1].set_title('Death Causes Rate: Miramar (Top {})'.format(rank))
- 21
- 22counts_er = erangel['killed_by'].value_counts()
- 23counts_mr = miramar['killed_by'].value_counts()
- 24
- 25sns.barplot(x=counts_er[:rank].index, y=[v / sum(counts_er) for v in counts_er.values][:rank], ax=axes[0] )
- 26sns.barplot(x=counts_mr[:rank].index, y=[v / sum(counts_mr) for v in counts_mr.values][:rank], ax=axes[1] )
- 27axes[0].set_ylim((0, 0.20))
- 28axes[0].set_xticklabels(counts_er.index, rotation=90)
- 29axes[1].set_ylim((0, 0.20))
- 30axes[1].set_xticklabels(counts_mr.index, rotation=90)
- 31
- 32#吃雞和武器的關係
- 33win = deaths[deaths["killer_placement"] == 1.0]
- 34win_causes = win['killed_by'].value_counts()
- 35
- 36sns.set_context('talk')
- 37fig = plt.figure(figsize=(20, 10))
- 38ax = sns.barplot(x=win_causes[:20].index, y=[v / sum(win_causes) for v in win_causes[:20].values])
- 39ax.set_title('Rate of Death Causes of Win')
- 40ax.set_xticklabels(win_causes.index, rotation=90)
4、隊友的助攻是否助我吃雞?
有時候一不留神就被擊倒了,還好我爬得快讓隊友救我。這裡選擇成功吃雞的隊伍,最終接受1次幫助的成員所在的團隊吃雞的概率為29%,所以說隊友助攻還是很重要的(再不要罵我豬隊友了,我也可以選擇不救你。)竟然還有讓隊友救9次的,你也是個人才。(手動滑稽)
- 1library(dplyr)
- 2library(tidyverse)
- 3library(data.table)
- 4library(ggplot2)
- 5pubg_full <- fread("E:/aggregate/agg_match_stats_0.csv")
- 6attach(pubg_full)
- 7pubg_winner <- pubg_full %>% filter(team_placement==1)
- 8detach(pubg_full)
- 9ggplot(data = pubg_winner) + geom_bar(mapping = aes(x = player_assists, y = ..count..), fill="#E69F00") +
- 10 xlim(0,10) + labs(title = "Number of Player assisted", x="Number of death")
- 11ggplot(data = pubg_winner) + geom_bar(mapping = aes(x = player_assists, y = ..prop..), fill="#56B4E9") +
- 12 xlim(0,10) + labs(title = "Number of Player assisted", x="Number of death")
5. 遠近戰與吃雞概率的關係
下圖是篩選出吃到雞的玩家,這是他們擊殺人頭的距離分佈
不難發現500米內的近戰佔了大多數,吃到雞的玩家更偏愛近戰,對敵人反應快。而長距離狙擊的大神只在少數,比如5000米以上,這些都是熟練操作8倍鏡了。
- last_seconds_erg = death.loc[(death['killer_placement'] == 1), :].dropna()
- distance = np.sqrt(((last_seconds_erg['killer_position_x'] - last_seconds_erg['victim_position_x']) / 100) ** 2 + (
- (last_seconds_erg['killer_position_y'] - last_seconds_erg['victim_position_y']) / 100) ** 2)
- distance = distance.apply(lambda x: int(x))
- labels = [0, 10, 30, 50, 100, 200, 500, 800, 1000, 1500, 2000, 3000, 5000, 10000, 20000]
- distan_cut = pd.cut(distance, bins=labels)
- distan_cut.value_counts().plot.bar(figsize=(10, 8))
- plt.savefig('out6.png', dpi=100)
6、團隊人越多我活得越久?
對資料中的party_size變數進行生存分析,可以看到在同一生存率下,四人團隊的生存時間高於兩人團隊,再是單人模式,所以人多力量大這句話不是沒有道理的。
7、乘車是否活得更久?
對死因分析中發現,也有不少玩家死於Bluezone,大家天真的以為撿繃帶就能跑毒。對資料中的player_dist_ride變數進行生存分析,可以看到在同一生存率下,有開車經歷的玩家生存時間高於只走路的玩家,光靠腿你是跑不過毒的。
8、小島上人越多我活得更久?
對game_size變數進行生存分析發現還是小規模的比賽比較容易存活。
- 1# R語言程式碼如下:
- 2library(magrittr)
- 3library(dplyr)
- 4library(survival)
- 5library(tidyverse)
- 6library(data.table)
- 7library(ggplot2)
- 8library(survminer)
- 9pubg_full <- fread("../agg_match_stats.csv")
- 10# 資料預處理,將連續變數劃為分類變數
- 11pubg_sub <- pubg_full %>%
- 12 filter(player_survive_time<2100) %>%
- 13 mutate(drive = ifelse(player_dist_ride>0, 1, 0)) %>%
- 14 mutate(size = ifelse(game_size<33, 1,ifelse(game_size>=33 &game_size<66,2,3)))
- 15# 建立生存物件
- 16surv_object <- Surv(time = pubg_sub$player_survive_time)
- 17fit1 <- survfit(surv_object~party_size,data = pubg_sub)
- 18# 視覺化生存率
- 19ggsurvplot(fit1, data = pubg_sub, pval = TRUE, xlab="Playing time [s]", surv.median.line="hv",
- 20 legend.labs=c("SOLO","DUO","SQUAD"), ggtheme = theme_light(),risk.table="percentage")
- 21fit2 <- survfit(surv_object~drive,data=pubg_sub)
- 22ggsurvplot(fit2, data = pubg_sub, pval = TRUE, xlab="Playing time [s]", surv.median.line="hv",
- 23 legend.labs=c("walk","walk&drive"), ggtheme = theme_light(),risk.table="percentage")
- 24fit3 <- survfit(surv_object~size,data=pubg_sub)
- 25ggsurvplot(fit3, data = pubg_sub, pval = TRUE, xlab="Playing time [s]", surv.median.line="hv",
- 26 legend.labs=c("small","medium","big"), ggtheme = theme_light(),risk.table="percentage")
9. 擊殺數與吃雞概率的關係
玩過農藥的的童鞋都會知道,收人頭收得越多,技能加成越大,傷害越來越大,無人能擋時就是勝利在望。而在吃雞裡面,能活到最後一個就是王者,所以很明顯擊殺人頭越多,吃到雞的概率並不一定大。那一場遊戲裡面,擊殺多少個算厲害來呢??
我們篩選比賽中所有排名第一的玩家,看看他們是擊殺數分佈:
看上圖是不是挺意外,單場比賽擊殺2個以內的佔多數,吃到雞的人也不例外,他們並不追求人頭,猥瑣發育也很重要.
小白玩家也不必擔心一場遊戲裡沒人頭,擊殺一兩個機器人也算是收穫不小來。
match_stats = pd.read_csv('F:/pubg-match-deaths/aggregate/agg_match_stats_0.csv')
winer = match_stats.loc[(match_stats['team_placement'] == 1), :].dropna()
labels = [0, 2, 5, 8, 11, 15, 20, 30, 40, 50]
winer['kill'] = pd.cut(winer['player_kills'], bins=labels)
winer['assist'] = pd.cut(winer['player_assists'], bins=labels)
winer['kill'].value_counts().plot.bar(figsize=(10, 10))
plt.savefig('out7.png', dpi=100)
10、最後毒圈有可能出現的地點?
面對有本事能苟到最後的我,怎麼樣預測最後的毒圈出現在什麼位置。從表agg_match_stats資料找出排名第一的隊伍,然後按照match_id分組,找出分組資料裡面player_survive_time最大的值,然後據此匹配表格kill_match_stats_final裡面的資料,這些資料裡面取第二名死亡的位置,作圖發現激情沙漠的毒圈明顯更集中一些,大概率出現在皮卡多、聖馬丁和別墅區。絕地海島的就比較隨機了,但是還是能看出軍事基地和山脈的地方更有可能是最後的毒圈。
- 1#最後毒圈位置
- 2import matplotlib.pyplot as plt
- 3import pandas as pd
- 4import seaborn as sns
- 5from scipy.misc.pilutil import imread
- 6import matplotlib.cm as cm
- 7
- 8#匯入部分資料
- 9deaths = pd.read_csv("deaths/kill_match_stats_final_0.csv")
- 10#匯入aggregate資料
- 11aggregate = pd.read_csv("aggregate/agg_match_stats_0.csv")
- 12print(aggregate.head())
- 13#找出最後三人死亡的位置
- 14
- 15team_win = aggregate[aggregate["team_placement"]==1] #排名第一的隊伍
- 16#找出每次比賽第一名隊伍活的最久的那個player
- 17grouped = team_win.groupby('match_id').apply(lambda t: t[t.player_survive_time==t.player_survive_time.max()])
- 18
- 19deaths_solo = deaths[deaths['match_id'].isin(grouped['match_id'].values)]
- 20deaths_solo_er = deaths_solo[deaths_solo['map'] == 'ERANGEL']
- 21deaths_solo_mr = deaths_solo[deaths_solo['map'] == 'MIRAMAR']
- 22
- 23df_second_er = deaths_solo_er[(deaths_solo_er['victim_placement'] == 2)].dropna()
- 24df_second_mr = deaths_solo_mr[(deaths_solo_mr['victim_placement'] == 2)].dropna()
- 25print (df_second_er)
- 26
- 27position_data = ["killer_position_x","killer_position_y","victim_position_x","victim_position_y"]
- 28for position in position_data:
- 29 df_second_mr[position] = df_second_mr[position].apply(lambda x: x*1000/800000)
- 30 df_second_mr = df_second_mr[df_second_mr[position] != 0]
- 31
- 32 df_second_er[position] = df_second_er[position].apply(lambda x: x*4096/800000)
- 33 df_second_er = df_second_er[df_second_er[position] != 0]
- 34
- 35df_second_er=df_second_er
- 36# erangel熱力圖
- 37sns.set_context('talk')
- 38bg = imread("erangel.jpg")
- 39fig, ax = plt.subplots(1,1,figsize=(15,15))
- 40ax.imshow(bg)
- 41sns.kdeplot(df_second_er["victim_position_x"], df_second_er["victim_position_y"], cmap=cm.Blues, alpha=0.7,shade=True)
- 42
- 43# miramar熱力圖
- 44bg = imread("miramar.jpg")
- 45fig, ax = plt.subplots(1,1,figsize=(15,15))
- 46ax.imshow(bg)
- 47sns.kdeplot(df_second_mr["victim_position_x"], df_second_mr["victim_position_y"], cmap=cm.Blues,alpha=0.8,shade=True)
分析結果
1. 平均使用者日線上時長2小時
從分佈圖上看大部分使用者都在1小時以上,最猛的幾個人超過8小時。
注:我這裡統計的是每一局的存活時間,實際線上時長會比我這個更長。
2. 女性角色被救次數高於男性
終於知道為什麼有那麼多人妖了,原來在遊戲裡面可以佔便宜啊。
3. 女性角色救人次數高於男性
給了大家一個帶妹上分的好理由。
4. 週五大家最忙
估計週五大家都要忙著交差和寫週報了。
5. 晚上22點是遊戲高峰
凌晨還有那麼多人玩,你們不睡覺嗎?
能拿到救死扶傷稱號的大部分都是女性角色,再一次證明玩遊戲要帶妹。 迴歸到這個遊戲的本質,那就是生存遊戲,沒什麼比活下來更重要的了。
結尾
這次查看了陌生人資料的場景才能提取到這麼多資料。我們可以通過同樣的手段來分析王者榮耀和其它遊戲的資料,有興趣的同學可以嘗試一下。 最後再說一下,98k是把好槍,配8 倍鏡非常爽。
最後祝大家: