王者榮耀這麼久了,還沒上王者?哈哈哈,看過來,是否是對英雄理解的不夠透徹呢,是否是尚未很好的爲英雄分類呢,今天就來看看英雄分類html
1、EM 聚類簡介python
2、爬取網上的英雄初始屬性值git
3、作成餅圖github
EM 英文名是 Expectation Maximization,也叫最大指望算法。算法
在統計計算中,最大指望(EM)算法是在機率(probabilistic)模型中尋找參數最大似然估計或者最大後驗估計的算法,其中機率模型依賴於沒法觀測的隱藏變量(Latent Variable)。bash
最大指望算法通過兩個步驟交替進行計算,第一步是計算指望(E),利用對隱藏變量的現有估計值,計算其最大似然估計值;第二步是最大化(M),最大化在 E 步上求得的最大似然值來計算參數的值。M 步上找到的參數估計值被用於下一個 E 步計算中,這個過程不斷交替進行。app
使用 sklearn 庫中的的 EM 聚類算法框架,採用高斯混合模型echarts
from sklearn.mixture import GaussianMixture
複製代碼
一些主要參數意義以下,其餘參數能夠查看相關文檔框架
n_components:混合高斯模型個數,也就是想要的聚類個數,默認爲1網站
covariance_type:協方差類型,包括{‘full’,‘tied’, ‘diag’, ‘spherical’}四種,分別對應徹底協方差矩陣(元素都不爲零),相同的徹底協方差矩陣(HMM會用到),對角協方差矩陣(非對角爲零,對角不爲零),球面協方差矩陣(非對角爲零,對角徹底相同,球面特性),默認‘full’ 徹底協方差矩陣
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/…