You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python绘制排序复选制选举的票数变化动画图表?

排序复选制(RCV)选举可视化与代码优化方案

一、Matplotlib动画实现与保存

使用FuncAnimation构建逐轮动画,通过animation.save导出为视频/GIF,需先安装依赖:

pip install matplotlib ffmpeg-python  # 导出MP4用ffmpeg,导出GIF替换为pillow

核心实现逻辑:

  • 每轮更新柱状图数据,将淘汰候选人的柱子设为红色高亮
  • 用箭头注释展示淘汰选票的流向
  • 动画帧对应流程:初始票数统计→高亮淘汰对象→展示选票拆分→更新下一轮结果

代码片段

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from collections import Counter

# 假设已实现RCV核心逻辑函数:返回当前轮票数、淘汰者、更新后选票、无效票数
def get_round_results(ballots, remaining_candidates):
    remaining_set = set(remaining_candidates)
    # 统计有效首选票
    top_candidates = [b[0] for b in ballots if b[0] in remaining_set]
    votes = Counter(top_candidates)
    for cand in remaining_candidates:
        votes.setdefault(cand, 0)
    # 计算无效选票
    exhausted = sum(1 for b in ballots if not set(b) & remaining_set)
    # 确定淘汰者(示例:票数最低者)
    eliminated = min(votes, key=votes.get) if len(remaining_candidates) > 1 else None
    # 模拟选票转移(实际需按RCV规则处理)
    updated_ballots = [b[1:] if b[0] == eliminated else b for b in ballots]
    return votes, eliminated, updated_ballots, exhausted

# 初始化图表
fig, ax = plt.subplots(figsize=(10,6))
bars = None
round_info = ax.text(0.02, 0.98, '', transform=ax.transAxes, va='top')

def init():
    ax.set_ylabel('票数')
    ax.set_title('排序复选制选举逐轮结果')
    return bars, round_info

def update(frame):
    global bars, ballots, remaining_candidates
    round_num = frame + 1
    current_votes, eliminated, ballots, exhausted = get_round_results(ballots, remaining_candidates)
    
    # 清除旧柱状图
    if bars:
        for bar in bars:
            bar.remove()
    
    # 准备绘图数据
    candidates = list(current_votes.keys()) + ['无效选票']
    vote_counts = list(current_votes.values()) + [exhausted]
    # 设置颜色:淘汰者标红,其余蓝色,无效票灰色
    colors = ['red' if c == eliminated else 'steelblue' for c in candidates[:-1]] + ['gray']
    
    # 绘制新柱状图
    bars = ax.bar(candidates, vote_counts, color=colors)
    
    # 更新轮次信息
    round_info.set_text(f"第{round_num}轮 | 淘汰: {eliminated or '无'} | 无效选票: {exhausted}")
    
    # 绘制选票流向箭头(示例:按比例模拟)
    if eliminated and round_num > 1:
        elim_votes = current_votes[eliminated]
        for i, cand in enumerate(candidates[:-1]):
            if cand != eliminated and cand in remaining_candidates:
                transfer = int(elim_votes * 0.3)  # 实际替换为真实转移票数
                ax.annotate(f"+{transfer}",
                            xy=(eliminated, elim_votes),
                            xytext=(cand, current_votes[cand]),
                            arrowprops=dict(arrowstyle='->', color='orange'))
    
    # 更新剩余候选人列表
    if eliminated:
        remaining_candidates.remove(eliminated)
    
    return bars, round_info

# 模拟测试数据
ballots = [['A', 'B', 'C'], ['B', 'A'], ['C', 'B'], ['A'], ['B', 'C'], ['C'], ['A', 'C'], ['B']]
remaining_candidates = ['A', 'B', 'C']

# 创建动画(轮次数量根据实际选举流程调整)
ani = FuncAnimation(fig, update, frames=3, init_func=init, blit=True, interval=2500)

# 保存动画
ani.save('rcv_election_animation.mp4', writer='ffmpeg', fps=0.4)  # 每帧停留2.5秒
# 若需GIF格式,替换为:
# ani.save('rcv_election_animation.gif', writer='pillow', fps=0.4)

plt.show()

二、字典遍历优化

替换低效的键遍历+手动计数,直接用collections.Counter和dict.items()简化逻辑:

原低效写法

votes = {}
for ballot in ballots:
    top_cand = ballot[0]
    if top_cand in votes:
        votes[top_cand] += 1
    else:
        votes[top_cand] = 1

优化写法

from collections import Counter

# 直接统计有效首选票
top_candidates = [b[0] for b in ballots if b[0] in remaining_candidates]
votes = Counter(top_candidates)
# 补全剩余候选人的0票记录
for cand in remaining_candidates:
    votes.setdefault(cand, 0)

三、无效选票计数简化

通过集合交集快速判断选票是否无有效候选人,替代多层循环:

原复杂写法

exhausted = 0
for ballot in ballots:
    has_valid = False
    for cand in ballot:
        if cand in remaining_candidates:
            has_valid = True
            break
    if not has_valid:
        exhausted += 1

简化写法

remaining_set = set(remaining_candidates)
exhausted = sum(1 for ballot in ballots if not set(ballot) & remaining_set)

内容的提问来源于stack exchange,提问作者Burmeind

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 09:22:48