把英雄分類,看 Python 帶你上王者

王者榮耀這麼久了,還沒上王者?哈哈哈,看過來,是否是對英雄理解的不夠透徹呢,是否是尚未很好的爲英雄分類呢,今天就來看看英雄分類html

技術棧

1、EM 聚類簡介python

2、爬取網上的英雄初始屬性值git

3、作成餅圖github

EM 聚類簡介

EM 英文名是 Expectation Maximization,也叫最大指望算法。算法

在統計計算中,最大指望(EM)算法是在機率(probabilistic)模型中尋找參數最大似然估計或者最大後驗估計的算法,其中機率模型依賴於沒法觀測的隱藏變量(Latent Variable)。bash

最大指望算法通過兩個步驟交替進行計算,第一步是計算指望(E),利用對隱藏變量的現有估計值,計算其最大似然估計值;第二步是最大化(M),最大化在 E 步上求得的最大似然值來計算參數的值。M 步上找到的參數估計值被用於下一個 E 步計算中,這個過程不斷交替進行。app

進行英雄聚類

使用 sklearn 庫中的的 EM 聚類算法框架,採用高斯混合模型echarts

from sklearn.mixture import GaussianMixture
複製代碼

一些主要參數意義以下,其餘參數能夠查看相關文檔框架

  1. n_components:混合高斯模型個數,也就是想要的聚類個數,默認爲1網站

  2. covariance_type:協方差類型,包括{‘full’,‘tied’, ‘diag’, ‘spherical’}四種,分別對應徹底協方差矩陣(元素都不爲零),相同的徹底協方差矩陣(HMM會用到),對角協方差矩陣(非對角爲零,對角不爲零),球面協方差矩陣(非對角爲零,對角徹底相同,球面特性),默認‘full’ 徹底協方差矩陣

  3. max_iter:最大迭代次數,默認100

因此能夠構造 GMM 聚類以下:

# 構造 GMM 聚類
gmm = GaussianMixture(n_components=20, covariance_type='full')
複製代碼

有一份以下結構的數據:

能夠看到,涉及到的屬性很是多,初始的屬性設置以下:

feature = ['1級物理攻擊', '15級物理攻擊', '每級成長',
           '1級生命', '15級生命', '生命成長值', '1級物理防護',
           '15級物理防護', '每級物理防護成長', '攻速成長',
           '1級每5秒回血', '15級每5秒回血', '1級最大法力',
           '15級最大法力', '最大法力成長', '1級每五秒回藍',
           '15級每5秒回藍', '近/遠程?', '移速', '定位', '我的建議分路']
複製代碼

屬性降維

能夠先經過熱力圖來判斷下哪些屬性是強相關的,只保留惟一屬性

import seaborn as sns
import matplotlib.pyplot as plt

corr = data[feature].corr()
plt.figure(figsize=(14, 14))
sns.heatmap(corr, annot=True)
plt.show()
複製代碼

能夠看到,其中」1級最大法力「,」15級最大法力「,」最大法力成長「,是強相關的,由此能夠作出屬性篩選,最終保留的屬性以下:

features_remain = ['15級生命', '15級物理攻擊',
                   '15級物理防護', '15級最大法力',
                   '15級每5秒回血', '15級每5秒回藍', '移速',
                   '攻速成長', '近/遠程?']
複製代碼

數據規範化

將攻擊範圍字段(」近/遠程?「)轉換爲 0 和 1

data_new['近/遠程?'] = data_new['近/遠程?'].map({'遠程': 1, '近程': 0})
複製代碼

EM 聚類計算

採用高斯混合模式,並把生成的類別寫入 csv 文件中

# 構造 GMM 聚類
 gmm = GaussianMixture(n_components=20, covariance_type='full')
 gmm.fit(data_new)
 
 # 訓練數據
 prediction = gmm.predict(data_new)
 # print(prediction)
 
 hero_data.insert(0, '分組', prediction)
 hero_data.to_csv('hero_out.csv', index=False, sep=',', encoding='gb18030')
複製代碼

餅圖輸出

爲了更加直觀的查看各個英雄的分組狀況,這裏使用餅圖來作可視化 首先取出數據的」分組「和」名稱「兩個字段,並對」分組「字段進行分組處理

df = hero_data[['分組', '名稱']]
grouped = df.groupby(['分組'])
複製代碼

而後取出分組中的數值,並用 pyecharts 來畫餅圖

from pyecharts import Pie
 
 k = []
 for name, group in grouped:
     k.append({name: list(group['名稱'].values)})
 
 kk = []
 for i in k:
     for k, v in i.items():
        kk.append(v)

length = []
key = []
for i in kk:
    key.append(str(i))
    length.append(len(i))
pie = Pie('英雄徹底屬性分類圖', title_pos='center')
pie.add("", key, length,
        is_label_show=True, legend_pos="bottom", legend_orient="vertical",)
pie.render()
複製代碼

抓取英雄初始屬性

要想得到更加全的英雄數據,仍是須要到網上抓取,這樣纔可以保證英雄的數量是最新的。這裏我使用的是 db.18183.com/ 網站的數據,頁面以下:

獲取英雄頁面 URL

使用 BeautifulSoup 來定位到 class 爲 mod-iconlist 的 ul 元素,裏面保存的就是各個英雄的頁面

url = 'http://db.18183.com/'
    url_list = []
    res = requests.get(url + 'wzry').text
    content = BeautifulSoup(res, "html.parser")
    ul = content.find('ul', attrs={'class': "mod-iconlist"})
    hero_url = ul.find_all('a')
    for i in hero_url:
        url_list.append(i['href'])
複製代碼

抓取詳細信息

循環抓取到的 URL 列表,抓取每一個英雄的詳細信息

base_url = 'http://db.18183.com/'
     detail_list = []
     for i in url:
         # print(i)
         res = requests.get(base_url + i).text
         content = BeautifulSoup(res, "html.parser")
         name_box = content.find('div', attrs={'class': 'name-box'})
         name = name_box.h1.text
         hero_attr = content.find('div', attrs={'class': 'attr-list'})
        attr_star = hero_attr.find_all('span')
        survivability = attr_star[0]['class'][1].split('-')[1]
        attack_damage = attr_star[1]['class'][1].split('-')[1]
        skill_effect = attr_star[2]['class'][1].split('-')[1]
        getting_started = attr_star[3]['class'][1].split('-')[1]
        details = content.find('div', attrs={'class': 'otherinfo-datapanel'})
        # print(details)
        attrs = details.find_all('p')
        attr_list = []
        for attr in attrs:
            attr_list.append(attr.text.split(':')[1].strip())
        detail_list.append([name, survivability, attack_damage,
                            skill_effect, getting_started, attr_list])
複製代碼

保存到 csv 文件

open 一個文件,把對應的列表字段存入

with open('all_hero_init_attr.csv', 'w', encoding='gb18030') as f:
         f.write('英雄名字,生存能力,攻擊傷害,技能效果,上手難度,最大生命,最大法力,物理攻擊,'
                 '法術攻擊,物理防護,物理減傷率,法術防護,法術減傷率,移速,物理護甲穿透,法術護甲穿透,攻速加成,暴擊概率,'
                 '暴擊效果,物理吸血,法術吸血,冷卻縮減,攻擊範圍,韌性,生命回覆,法力回覆\n')
         for i in details:
             try:
                 rowcsv = '{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}'.format(
                     i[0], i[1], i[2], i[3], i[4], i[5][0], i[5][1], i[5][2], i[5][3], i[5][4], i[5][5],
                     i[5][6], i[5][7], i[5][8], i[5][9], i[5][10], i[5][11], i[5][12], i[5][13], i[5][14], i[5][15],
                    i[5][16], i[5][17], i[5][18], i[5][19], i[5][20]
                )
                f.write(rowcsv)
                f.write('\n')
            except:
                continue
複製代碼

數據清理

由於這個網站可能作的不是很用心,有些屬性會存在兩個百分號和爲空的狀況,如圖:

因此須要處理下。

對於兩個百分號,直接使用 notepad++ 把全部的 %% 的替換爲單 % 便可

對於爲空的字段,使用以下代碼處理,填爲 0

# 把空值設置爲0
data_init = data_init.fillna(0)
複製代碼

完成

對於數據規範化,GMM 聚類和餅圖呈現,都和前面相似,再也不贅述,下面來看看餅圖效果

雖然經過這兩張餅圖,沒有辦法一會兒提升你手殘的毛病,可是明確了英雄的分類,不是離王者更近了一步嗎

完整代碼在這裏: github.com/zhouwei713/…

相關文章
相關標籤/搜索