Py学习  »  Python

稳稳吃鸡!用Python可视化分析 ”绝地求生1800万游戏数据“,

Python网络爬虫与数据挖掘 • 5 年前 • 510 次点击  

作者:Tong_T

地址:https://blog.csdn.net/Tong_T/article/details/80378446

经常玩吃鸡游戏,我们现在来分析一下过去一年 1800万条游戏数据,看看有什么套路帮我们吃到鸡。

1. 数据集描述

做数据分析或者机器学习的我们,对于数据是很敏感的。本文数据来自 Kaggle,分游戏场次数据和玩家击杀数据两部分,各有10G左右。

Kaggle datasets: PUBG Match Deaths and Statistics,

地址: https://www.kaggle.com/skihikingkevin/pubg-match-deaths

视频游戏是数据提取的一个丰富领域。诸如复杂的魔兽世界补血以及侠盗猎车手自动驾驶汽车等知名例子告诉我们,视频游戏比我们真正想象的更接近现实。数据科学家可以深入了解玩家在假想和虚拟场景中所面临的逻辑和决策。

在这个Kaggle数据集中,我提供了来自流行游戏PlayerUnknown’s Battlegrounds的超过720,000场竞技比赛。数据来自pubg.op.gg,一个游戏追踪器网站。我打算让这个数据集纯粹是探索性的,但用户可以自由创建他们认为合适的预测模型。

PUBG是第一个/第三人称射击游戏royale风格的游戏,与超过90名玩家在一个大岛上相遇,在这个大岛上,团队和玩家一直战斗直到死亡。玩家从飞机上空投到岛上,在那里他们将清除城镇和建筑物的武器,弹药,装甲和急救设备。然后玩家将决定与最后一个站立的终极目标战斗或隐藏。一个蓝色区域将在游戏中出现几分钟,通过对站在蓝色区域内的任何人造成伤害并阻止任何处于安全区域内的人员,将玩家拉近和靠近在一起。

该数据集提供了两个部分:聚合和死亡。

在死亡数据中,这些档案记录了在720k比赛中发生的每一次死亡。也就是说,每一行都记录了一名玩家在比赛中死亡的事件。

在聚合数据中,总结每个比赛的元信息和玩家统计数据(由pubg提供)。它包括各种综合统计数据,例如玩家击杀,伤害,步行距离等,以及比赛本身的元数据,如队列大小,fpp / tpp,日期等。未压缩的数据分成5块,每块大约2GB。

解释位置数据:X,Y坐标全部在游戏内坐标中,需要线性缩放以在方形erangel和miramar地图上绘制。最小,最大坐标分别为0,800,000。

2. 开场跳哪里,可以避免落地成盒?

不少玩家吐槽游戏刚开始几分钟就落地成盒,游戏体验不好。其实跳伞选一个安全的地方降落很重要。首先来看开场4分钟内落地成盒的地点。

看到上图是否恍然大悟,深红色的地方就是最危险的,海岛地图上分别是军事基地、学校、P城、G港、防空洞,而沙漠地图最明显,扎堆两个地方:圣马丁城和皮卡多城。

那跳哪里是安全且资源又多的呢? 海岛地图上Y城和P港就是常常被人群遗忘的地方,可以放心搜。其实也不难发现,海岸沿线以及桥头位置都是安全地,跳伞跳到这,落地成盒到概率会大大降低。

代码如下:

import pandas as pd
from scipy.ndimage.filters import gaussian_filter
import matplotlib.cm as cm
from matplotlib.colors import Normalize
from scipy.misc.pilutil import imread
import numpy as np
import matplotlib.pyplot as plt

# 先把玩家被击杀的数据导入
death_0 = pd.read_csv('F:\pubg-match-deaths\deaths\kill_match_stats_final_0.csv')
death_1 = pd.read_csv('F:\pubg-match-deaths\deaths\kill_match_stats_final_1.csv', nrows=5000000)
death = death_0.merge(death_1, how='outer')
print(death.shape)
# (18426348, 12)

# 筛选落地成盒的玩家(选取开局4分钟之内死亡的玩家)
in_240_seconds_erg = death.loc[(death['map'] == 'ERANGEL') & (death['time'] < 240), :].dropna()
in_240_seconds_mrm = death.loc[(death['map'] == 'MIRAMAR') & (death['time'] < 240), :].dropna()

data_erg = in_240_seconds_erg[['victim_position_x', 'victim_position_y']].values
data_mrm = in_240_seconds_mrm[['victim_position_x', 'victim_position_y']].values
data_erg = data_erg * 4096 / 800000
data_mrm = data_mrm * 1000 / 800000

def heatmap(x, y, s, bins=100):
   heatmap, xedges, yedges = np.histogram2d(x, y, bins=bins)
   heatmap = gaussian_filter(heatmap, sigma=s)

   extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]
   return heatmap.T, extent

bg = imread('F:\pubg-match-deaths\erangel.jpg')
hmap, extent = heatmap(data_erg[:, 0], data_erg[:, 1], 4.5)
alphas = np.clip(Normalize(0, hmap.max(), clip=True)(hmap) * 4.5, 0.0, 1.)
colors = Normalize(0, hmap.max(), clip=True)(hmap)
colors = cm.Reds(colors)
colors[..., -1] = alphas

fig, ax = plt.subplots(figsize=(24, 24))
ax.set_xlim(0, 4096)
ax.set_ylim(0, 4096)
ax.imshow(bg)
ax.imshow(colors, extent=extent, origin='lower', cmap=cm.Reds, alpha=0.9)
plt.gca().invert_yaxis()
plt.savefig('out1.png', dpi=100)

bg = imread('F:\pubg-match-deaths\miramar.jpg')
hmap, extent = heatmap(data_mrm[:, 0], data_mrm[:, 1], 4.5)
alphas = np.clip(Normalize(0, hmap.max(), clip=True)(hmap) * 4.5, 0.0, 1.)
colors = Normalize(0, hmap.max(), clip=True)(hmap)
colors = cm.Reds(colors)
colors[..., -1] = alphas

fig, ax = plt.subplots(figsize=(24, 24))
ax.set_xlim(0, 1000)
ax.set_ylim(0, 1000)
ax.imshow(bg)
ax.imshow(colors, extent=extent, origin='lower', cmap=cm.Reds, alpha=0.9)
plt.gca().invert_yaxis()
plt.savefig('out2.png', dpi=100)

3. 哪里才是最佳吃鸡地点?

没有落地成盒那谁都有机会吃鸡。装备可以很快捡完,玩得溜的大神当然是四处搜人舔包,而大多数普通玩家会选择往毒圈内跑,然后躲起来。瞎跑会有很大概率被狙击。现在关心的是哪里是决赛圈的概率最大?我们直接跑向决赛圈,也就是吃鸡率较高的地方,当个伏地魔,人来了先下手狙人

以上两图分别是海岛和沙漠地图最终吃鸡地点的分部分图。可以看出,决赛圈的位置分布很广,第一次缩圈后的每个位置都有可能是决赛圈,而概率比较大的几个地方,跟跳伞扎堆的地方基本一致,而且是地图的中心处。捡完装备往中心跑倒是个不错的选择。

另外联想到一个问题,决赛圈和扎堆跳伞的位置重合,那是不是说明吃鸡的大神在跳伞落地后都不会移动太远,而只是在落地附近打埋伏?

代码如下:

last_seconds_erg = death.loc[(death['map'] == 'ERANGEL') & (death['killer_placement'] == 1), :].dropna()
last_seconds_mrm = death.loc[(death['map'] == 'MIRAMAR') & (death['killer_placement'] == 1), :].dropna()
data_erg = last_seconds_erg[['victim_position_x', 'victim_position_y']].values
data_mrm = last_seconds_mrm[['victim_position_x', 'victim_position_y']].values
data_erg = data_erg * 4096 / 800000
data_mrm = data_mrm * 1000 / 800000

bg = imread('F:\pubg-match-deaths\erangel.jpg')
hmap, extent = heatmap(data_erg[:, 0], data_erg[:, 1], 4.5)
alphas = np.clip(Normalize(0, hmap.max(), clip=True)(hmap) * 4.5, 0.0, 1.)
colors = Normalize(0, hmap.max(), clip=True)(hmap)
colors = cm.Reds(colors)
colors[..., -1] = alphas

fig, ax = plt.subplots(figsize=(24, 24))
ax.set_xlim(0, 4096)
ax.set_ylim(0, 4096)
ax.imshow(bg)
ax.imshow(colors, extent=extent, origin='lower', cmap=cm.Reds, alpha=0.9)
plt.gca().invert_yaxis()
plt.savefig('out3.png', dpi=100)

last_seconds_mrm = death.loc[(death['map'] == 'MIRAMAR') & (death['killer_placement'] == 1), :].dropna()
data_erg = last_seconds_erg[['victim_position_x', 'victim_position_y']].values
data_mrm = last_seconds_mrm[['victim_position_x', 'victim_position_y']].values
data_erg = data_erg * 4096 / 800000
data_mrm = data_mrm * 1000 / 800000

bg = imread('F:\pubg-match-deaths\miramar.jpg')
hmap, extent = heatmap(data_mrm[:, 0], data_mrm[:, 1 ], 4.5)
alphas = np.clip(Normalize(0, hmap.max(), clip=True)(hmap) * 4.5, 0.0, 1.)
colors = Normalize(0, hmap.max(), clip=True)(hmap)
colors = cm.Reds(colors)
colors[..., -1] = alphas

fig, ax = plt.subplots(figsize=(24, 24))
ax.set_xlim(0, 1000);
ax.set_ylim(0, 1000)
ax.imshow(bg)
ax.imshow(colors, extent=extent, origin='lower', cmap=cm.Reds, alpha=0.9)
plt.gca().invert_yaxis()
plt.savefig('out4.png', dpi=100)

4. 选择带什么武器容易吃鸡?

相信不少玩家最关心这个。来看图:

上图是所有吃到鸡的玩家所佩带的武器分布,自动步枪M416 是他们的最爱。也可以发现,他们带自动步枪比狙击步枪要多很多。狙击枪里面,98k赫赫有名也是名副其实。
既然吃到鸡的玩家带的步枪多,那是否说明他们优先选择近战,而不是远距离狙击??

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. 击杀数与吃鸡概率的关系

玩过农药的的童鞋都会知道,收人头收得越多,技能加成越大,伤害越来越大,无人能挡时就是胜利在望。而在吃鸡里面,能活到最后一个就是王者,所以很明显击杀人头越多,吃到鸡的概率并不一定大。那一场游戏里面,击杀多少个算厉害来呢??

我们筛选比赛中所有排名第一的玩家,看看他们是击杀数分布:

看上图是不是挺意外,单场比赛击杀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)

学习Python和网络爬虫,关注公众号:datanami

近期文章:

  1. 福利 | 分享一个免费学习Python爬虫的机会

  2. 用 Python 实现打飞机

  3. 给Python新手的一道面试题:如何正确读写文件

  4. wtfPython—Python中一些奇妙的代码

  5. Python爬虫库-Beautiful Soup的使用

  6. 秒懂系列 | 史上最简单的Python Django入门教程


今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/yjb3nszy6j
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/21241
 
510 次点击