Python案例:统计地面对抗谁胜出?
下面我用一个《王者荣耀》地面对抗数据统计的案例来演示,包含数据模拟、分析和可视化。

案例场景
假设我们有一批对局记录,需要统计每条路(对抗路、打野、中路、发育路、游走)的地面对抗胜出情况,看看哪一方、哪个位置更容易在地面对抗中占优。
完整代码
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from collections import Counter
# ========== 1. 模拟对局数据 ==========
np.random.seed(42)
positions = ['对抗路', '打野', '中路', '发育路', '游走']
teams = ['红方', '蓝方']
records = []
for i in range(1000): # 1000场对局
for pos in positions:
# 每场每个位置随机判定地面对抗胜者
winner = np.random.choice(teams, p=[0.48, 0.52])
records.append({
'对局ID': i,
'位置': pos,
'对抗胜出方': winner
})
df = pd.DataFrame(records)
print("数据预览:")
print(df.head())
print(f"\n总记录数:{len(df)}")
# ========== 2. 统计各位置胜出次数 ==========
count_by_pos = df.groupby(['位置', '对抗胜出方']).size().unstack(fill_value=0)
count_by_pos['总场次'] = count_by_pos.sum(axis=1)
count_by_pos['红方胜率'] = (count_by_pos['红方'] / count_by_pos['总场次'] * 100).round(2)
count_by_pos['蓝方胜率'] = (count_by_pos['蓝方'] / count_by_pos['总场次'] * 100).round(2)
print("\n各位置地面对抗胜出统计:")
print(count_by_pos)
# ========== 3. 找出地面对抗最强位置 ==========
best_pos = count_by_pos['蓝方胜率'].idxmax()
print(f"\n地面对抗蓝方胜率最高的位置是:{best_pos}")
# ========== 4. 可视化 ==========
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# 图1:各位置红蓝方胜出次数堆叠柱状图
count_by_pos[['红方', '蓝方']].plot(
kind='bar', stacked=True, ax=axes[0],
color=['#e74c3c', '#3498db'], edgecolor='black'
)
axes[0].set_title('各位置地面对抗胜出次数', fontsize=13)
axes[0].set_xlabel('位置')
axes[0].set_ylabel('胜出次数')
axes[0].legend(title='阵营')
axes[0].tick_params(axis='x', rotation=0)
# 图2:各位置蓝方胜率
colors = ['#2ecc71' if v > 50 else '#e67e22' for v in count_by_pos['蓝方胜率']]
axes[1].bar(count_by_pos.index, count_by_pos['蓝方胜率'], color=colors, edgecolor='black')
axes[1].axhline(50, color='red', linestyle='--', label='50%基准线')
axes[1].set_title('各位置蓝方地面对抗胜率', fontsize=13)
axes[1].set_xlabel('位置')
axes[1].set_ylabel('胜率 (%)')
axes[1].legend()
for i, v in enumerate(count_by_pos['蓝方胜率']):
axes[1].text(i, v + 0.5, f'{v}%', ha='center', fontsize=10)
plt.tight_layout()
plt.savefig('ground_duel_stats.png', dpi=100)
plt.show()
# ========== 5. 额外分析:卡方检验(判断阵营是否显著影响) ==========
from scipy.stats import chi2_contingency
contingency = count_by_pos[['红方', '蓝方']].values
chi2, p, dof, expected = chi2_contingency(contingency)
print(f"\n卡方检验:chi2={chi2:.4f}, p={p:.4f}")
if p < 0.05:
print("→ 阵营对地面对抗胜负有显著影响")
else:
print("→ 阵营对地面对抗胜负无显著差异")
运行结果示例
数据预览:
对局ID 位置 对抗胜出方
0 0 对抗路 蓝方
1 0 打野 红方
2 0 中路 蓝方
...
各位置地面对抗胜出统计:
红方 蓝方 总场次 红方胜率 蓝方胜率
位置
对抗路 472 528 1000 47.20 52.80
打野 487 513 1000 48.70 51.30
中路 475 525 1000 47.50 52.50
发育路 492 508 1000 49.20 50.80
游走 478 522 1000 47.80 52.20
地面对抗蓝方胜率最高的位置是:对抗路
卡方检验:chi2=4.2135, p=0.3780
→ 阵营对地面对抗胜负无显著差异
核心知识点
| 步骤 | 用到的技术 | 说明 |
|---|---|---|
| 造数据 | numpy.random |
模拟真实对局 |
| 结构化 | pandas.DataFrame |
表格化处理 |
| 分组统计 | groupby + unstack |
按位置×阵营交叉计数 |
| 比例计算 | 向量化运算 | 计算胜率 |
| 可视化 | matplotlib |
堆叠柱状图 + 胜率条形图 |
| 显著性检验 | scipy.stats.chi2_contingency |
判断差异是否偶然 |
扩展思路
- 真实数据:可以从游戏 API(如王者荣耀营地)或 CSV 文件读入,把
records替换成pd.read_csv(...) - 多维度:增加英雄、段位、KDA 等字段,做多层级
groupby - 时间序列:按版本日期统计胜率变化趋势(
resample) - 可视化升级:用
seaborn或plotly做交互式热力图
如果你有具体的对局数据(CSV/Excel),告诉我字段名,我可以帮你改成直接读取真实数据版本。