【Python 数据可视化】复刻 B 站爆款世界人口动态排序轮播图(Bar Chart Race)完整实战
文章简介
动态排序柱状图(Bar Chart Race)是 B 站、抖音等平台超火的数据可视化形式,直观又有视觉冲击力。本文基于 Python + Pandas + Pyecharts,从零完成1960-2024 世界各国人口动态轮播图开发,包含数据清洗、宽表转长表、黑名单过滤无效数据、B 站风格深色美化、时间轴轮播、交互优化全流程,代码可直接运行,最终产出可在浏览器打开的 HTML 动态图表。
技术栈:Python3 + Pandas + Pyecharts5 + ECharts实现效果:自动轮播、暂停 / 播放、年份手动切换、悬浮数据提示、动态彩色圆角柱状图、纯主权国家数据(剔除大洲 / 地区 / 非主权领地)
一、项目背景与目标
1.1 项目背景
动态排序轮播图(Bar Chart Race)是数据可视化经典样式,在 B 站数据类视频中出镜率极高。本次项目使用世界人口数据集,还原 1960-2024 年全球各国人口排名变迁,复刻 B 站同款视觉风格。
1.2 核心实现目标
- 数据纯净:过滤大洲、收入分组、海外领地、地区汇总等无效数据,仅保留 195 个主权国家;
- 动态排序:按年份自动轮播,人口越多国家排名越靠前;
- 全交互:悬浮查看人口数值、播放 / 暂停、手动切换年份;
- 视觉美化:深色 B 站风格、动态配色、圆角柱状图、流畅轮播动画。
二、环境与依赖准备
2.1 安装依赖库
运行代码前,先安装所需第三方库:
bash
运行
pip install pandas pyecharts
2.2 核心技术说明
- Pandas:数据读取、空值处理、黑名单过滤、宽表转长表数据重塑;
- Pyecharts:绘制横向柱状图 + Timeline 时间轴实现轮播;
- JsCode:实现柱子动态循环配色;
- CDN 配置:修复国内网络 ECharts 加载空白问题(关键配置)。
三、完整代码实现(分步讲解)
3.1 整体导入库 + 修复国内 CDN(必加)
国内网络直接运行 Pyecharts 极易出现 HTML 空白,必须替换 CDN 地址:
python
运行
# 导入核心库
import pandas as pd
from pyecharts.charts import Bar, Timeline
from pyecharts import options as opts
from pyecharts.globals import ThemeType, CurrentConfig
from pyecharts.commons.utils import JsCode
# 修复国内CDN,解决HTML图表空白问题(重中之重)
CurrentConfig.ONLINE_HOST = "https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/"
3.2 数据加载与初步探查
数据集:世界人口数据-中文版(1960-2024).csv,文件编码为gbk,放置在./data/目录下。
python
运行
# 读取CSV人口数据
df = pd.read_csv('./data/世界人口数据-中文版(1960-2024).csv', encoding='gbk')
# 查看数据前5行
print(df.head())
# 查看数据结构、缺失值
print(df.info())
原始数据说明:
- 共 266 行数据,包含国家、大洲、地区汇总等内容;
- 70 列:4 列基础属性(国家名称、代码等)+ 1960-2025 年份列;
- 2025 年数据全部为空,有效年份:1960-2024。
3.3 核心数据清洗(剔除无效数据)
原始数据包含大量大洲、收入分组、非主权领地、地区汇总,需要通过黑名单精准过滤。
3.3.1 划分属性列与年份列
python
运行
# 提取固定属性列(国家名称、编码等)
attr_cols = ["Country Name", "Country Code", "Indicator Name", "Indicator Code"]
# 提取所有年份列(纯数字列)
year_cols = [col for col in df.columns if str(col).isdigit()]
3.3.2 黑名单过滤(剔除非主权国家)
定义黑名单,过滤全球汇总、大洲、收入等级、海外领地、港澳台地区等无效数据:
python
运行
# 黑名单:过滤所有非主权国家、汇总区域、领地
black_list = [
# 全球 & 大洲汇总
"世界", "北美", "东亚与太平洋地区", "欧洲与中亚地区",
"东亚与太平洋地区(不包括高收入)", "欧洲与中亚地区(不包括高收入)",
"拉丁美洲与加勒比海地区", "拉丁美洲与加勒比海地区(不包括高收入)",
"中东、北非、阿富汗与巴基斯坦", "中东与北非地区(不包括高收入)",
"撒哈拉以南非洲地区", "撒哈拉以南非洲地区(不包括高收入)",
"南亚", "小国", "加勒比小国", "太平洋岛国", "其他小国",
"未分类国家", "阿拉伯联盟国家", "欧洲联盟", "欧洲货币联盟",
"经合组织成员", "重债穷国 (HIPC)", "脆弱和受衝突影響的情況下",
# 收入等级分类
"高收入国家", "低收入国家", "中等收入国家",
"中高等收入国家", "中低等收入国家", "中低收入国家",
# 人口红利分类
"早人口紅利", "後期人口紅利", "預人口紅利", "人口紅利之後",
# 发展水平分类
"最不发达国家:联合国分类",
# 世界银行分组
"IBRD与IDA", "只有IBRD", "只有IDA", "IDA總", "IDA混合",
"东亚与太平洋地区 (IBRD与IDA)", "欧洲与中亚地区 (IBRD与IDA)",
"拉丁美洲与加勒比海地区 (IBRD与IDA)", "中东与北非地区 (IBRD与IDA)",
"南亚 (IBRD与IDA)", "撒哈拉以南非洲地区 (IBRD与IDA)",
# 非主权领地、海外地区
"阿鲁巴", "美属萨摩亚", "百慕大", "库拉索", "开曼群岛",
"海峡群岛", "法罗群岛", "直布罗陀", "格陵兰", "关岛",
"中国香港特别行政区", "中国澳门特别行政区", "圣马丁(法属)",
"圣马丁(荷属)", "北马里亚纳群岛", "新喀里多尼亚", "波多黎各",
"约旦河西岸和加沙", "法属波利尼西亚", "特克斯科斯群岛",
"英屬維爾京群島", "美属维京群岛", "科索沃"
]
# 反向过滤:保留不在黑名单中的数据
df = df[~df["Country Name"].isin(black_list)].reset_index(drop=True)
print("过滤后剩余主权国家数量:", df["Country Name"].nunique())
3.4 宽表转长表(数据重塑)
原始数据是宽格式(一行国家,多年份并列),时序轮播图需要长格式(一行 = 一个国家 + 一个年份 + 人口),使用pd.melt()完成转换:
python
运行
# 宽表转为长表,生成 Year、Population 字段
df_long = pd.melt(
df,
id_vars=attr_cols,
value_vars=year_cols,
var_name="Year", # 拆分后的年份列名
value_name="Population" # 拆分后的人口列名
)
# 数据类型转换 + 清除空值
df_long["Year"] = df_long["Year"].astype(int)
df_long["Population"] = pd.to_numeric(df_long["Population"], errors="coerce")
# 删除人口为空的行(剔除2025无效数据)
df_clean = df_long.dropna(subset=["Population"])
# 只保留核心三列:国家、年份、人口
df_clean = df_clean[["Country Name", "Year", "Population"]]
print("清洗后有效数据条数:", len(df_clean))
3.5 核心可视化:B 站风格动态轮播图
包含动态配色、圆角柱子、深色背景、时间轴轮播、交互优化全套美化配置。
3.5.1 定义动态配色 JS 代码
实现柱子循环变色,提升视觉效果:
python
运行
# 动态颜色配置:不同排名柱子自动切换颜色
color_js = JsCode("""
function(params){
let c = ['#ff4757','#ffa502','#fffa65','#2ed573','#1e90ff','#3742fa','#a55eea','#48dbfb'];
return c[params.dataIndex % c.length];
}
""")
3.5.2 初始化时间轴 + 画布样式
采用 B 站同款极深黑背景 + 深色主题,设置大屏尺寸:
python
运行
# 初始化时间轴组件(整体画布)
timeline_final = Timeline(
init_opts=opts.InitOpts(
width="1600px",
height="850px",
theme=ThemeType.DARK,
bg_color="#080808" # 极深黑色背景,B站风格
)
)
# 获取所有年份列表
year_list = df_clean["Year"].unique().tolist()
3.5.3 遍历年份,逐一生成柱状图
关键排序逻辑:数据升序 + 坐标轴反转,保证人口最多的国家显示在图表最上方。
python
运行
for year in year_list:
# 筛选当前年份数据,取人口Top20
year_data = df_clean[df_clean["Year"] == year].sort_values("Population", ascending=False).head(20)
# 反转排序:配合reversal_axis实现从上到下降序
year_data = year_data.sort_values("Population", ascending=True)
# 拆分数据
country_list = year_data["Country Name"].tolist()
pop_list = year_data["Population"].tolist()
# 构建单年份横向柱状图
bar = (
Bar()
.add_xaxis(country_list)
.add_yaxis(
series_name="人口数量",
y_axis=pop_list,
itemstyle_opts=opts.ItemStyleOpts(
color=color_js, # 动态配色
opacity=0.85, # 透明度
border_radius=7 # 圆角柱子
),
label_opts=opts.LabelOpts(
is_show=True,
position="right",
color="#ffffff",
font_size=11,
formatter="{c} 人"
)
)
.reversal_axis() # 反转坐标轴(横向柱状图核心)
.set_global_opts(
title_opts=opts.TitleOpts(
title=f"{year}年 世界各国人口Top20",
title_textstyle_opts=opts.TextStyleOpts(color="#ffffff", font_size=20)
),
tooltip_opts=opts.TooltipOpts(
trigger="axis",
formatter="<b>{b}</b><br>人口:{c}"
),
legend_opts=opts.LegendOpts(is_show=False)
)
)
# 将当年图表加入时间轴
timeline_final.add(bar, str(year))
3.5.4 时间轴轮播样式配置
设置自动播放、循环、切换速度、时间轴美化:
python
运行
# 时间轴全局配置
timeline_final.add_schema(
is_auto_play=True, # 自动播放
is_loop_play=True, # 循环播放
play_interval=600, # 切换间隔600ms,丝滑轮播
is_timeline_show=True,
pos_left="center",
width="95%",
# 时间轴文字样式
label_opts=opts.LabelOpts(color="#ffffff", font_size=11, font_weight="bold"),
# 时间轴线样式
linestyle_opts=opts.LineStyleOpts(color="#00a1ff", width=4),
# 时间轴节点样式
itemstyle_opts=opts.ItemStyleOpts(color="#00a1ff", border_color="#ffffff", border_width=2)
)
3.5.5 导出 HTML 文件
python
运行
# 生成HTML文件,浏览器直接打开运行
timeline_final.render("B站同款人口动态排行.html")
# Jupyter Notebook 内直接预览(可选)
# timeline_final.render_notebook()
四、运行效果与功能说明
4.1 输出文件
运行代码后,目录下会生成 B站同款人口动态排行.html,使用任意浏览器打开即可查看。
4.2 核心功能
- 自动轮播:从 1960 年自动切换至 2024 年,循环播放;
- 手动控制:点击底部时间轴可自由切换年份,支持暂停 / 播放;
- 悬浮提示:鼠标放在柱子上,显示国家名称 + 精确人口数;
- 视觉效果:深色 B 站风格、彩色圆角柱状图、排名动态变化;
- 数据纯净:仅展示 195 个主权国家,无大洲、地区汇总干扰。
五、项目重难点总结
- CDN 配置:国内网络必须替换 ECharts CDN,否则 HTML 图表空白;
- 数据清洗:黑名单过滤是核心,剔除汇总数据才能保证排名准确;
- 宽表转长表:
pd.melt()是时序可视化的常用数据重塑方法; - 排序 + 坐标轴反转:先升序再反转 Y 轴,实现 “人口越多越靠上” 的展示逻辑;
- 动态配色:通过 JsCode 结合索引取色,实现柱子循环变色。
六、项目拓展优化方向
- 添加国旗:在国家标签中嵌入 Base64 国旗图片,提升视觉体验;
- 多指标切换:扩展下拉框,支持人口增长率、GDP 等数据切换轮播;
- 性能优化:大数据量下预计算每年 Top20 数据,减少前端渲染压力;
- 单位优化:人口数值改为 “万人 / 亿人” 单位,数字展示更简洁。
七、完整项目总结
本项目完整走完数据读取→数据探查→清洗过滤→数据重塑→可视化美化全流程,是 Pandas + Pyecharts 综合实战的经典案例。复刻出的动态轮播图完美对标 B 站主流数据视频风格,代码注释完整、可直接复用,适合 Python 数据分析、数据可视化入门学习。
配套文件说明
- 数据集:
世界人口数据-中文版(1960-2024).csv(放置在./data/文件夹); - 运行环境:Python3.7+;
- 运行方式:PyCharm / Jupyter / VS Code 均可。
更多推荐
所有评论(0)