刷 B 站时总能被各式各样的动态柱状排名图(Bar Chart Race)吸引,时序轮播、自动排序、丝滑动画,把数据变迁展现得生动又直观。今天就带大家完整复刻同款效果,基于pandas+pyecharts,打造 1960-2024 年世界各国人口动态排名轮播图,从数据清洗、格式转换到美化交互,手把手走完完整数据分析可视化流程。
一、项目整体介绍
1.1 项目背景
动态排序轮播图是当下非常流行的数据可视化形式,凭借动态轮播、实时排名的特点,成为科普、数据分析类视频的常用表现手法。
本次项目选用1960-2024 年全球人口数据集,通过 Python 完成数据处理与可视化,还原 B 站风格的人口动态排名,直观展现六十余年间世界各国人口数量的起伏与位次变化。
1.2 项目目标
- 数据纯净化:剔除大洲、收入分组、非主权地区等无效数据,仅保留真实主权国家数据;
- 动态排序展示:按年份自动轮播,每年人口数量降序排列,人口越多排名越靠前;
- 全交互体验:支持鼠标悬浮查看详细人口、播放 / 暂停、手动切换年份;
- 视觉美化:采用深色主题、动态配色、圆角柱状条,达到商业化可视化效果。
1.3 技术栈
- 编程语言:Python 3.x
- 数据处理:
pandas(数据读取、清洗、宽长表转换) - 可视化库:
pyecharts(柱状图 + 时间线轮播组件) - 辅助工具:
JsCode实现动态配色、CDN 配置解决国内加载问题
二、环境准备与依赖导入
首先导入项目所需全部库,同时配置国内 CDN 地址,解决 pyecharts 生成 HTML 后空白无法渲染的常见问题,这也是国内使用该库的必备操作。
python
运行
# 导入核心库 from pyecharts.charts import Bar, Timeline import pandas as pd from pyecharts import options as opts from pyecharts.globals import ThemeType, CurrentConfig from pyecharts.commons.utils import JsCode # 配置国内CDN,解决图表加载空白 CurrentConfig.ONLINE_HOST = "https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/"三、数据加载与初步探查
本次使用1960-2024 中文版世界人口 CSV 数据集,文件包含国家名称、国家代码、历年人口等信息,由于是中文文件,读取时指定gbk编码。
3.1 读取数据
python
运行
# 读取本地人口数据集,根据你的文件路径修改地址 df = pd.read_csv('世界人口数据-中文版(1960-2024).csv', encoding='gbk') # 查看前5行数据 df.head()3.2 数据结构分析
原始数据集为宽表结构:
- 共 266 行数据,包含国家、大洲汇总、地区分组等内容;
- 总计 70 列,4 列基础属性(国家名称、代码、指标等),66 列为 1960-2025 年人口数据;
- 2025 年数据全部为空值,有效数据区间为 1960-2024 年。
可以明显看到,原始数据混杂了各大洲、经济分组的汇总数据,还有海外领地、特别行政区等非主权地区,无法直接用于绘图,必须进行深度清洗。
四、核心数据清洗与格式转换
数据清洗是本项目的重中之重,直接决定最终图表的准确性,主要分为四大步骤。
4.1 黑名单过滤:剔除无效数据
我们自定义黑名单,过滤三类无效数据:全球 / 大洲汇总、收入等级分组、非主权地区 / 领地,只保留正规主权国家。
python
运行
# 定义黑名单:汇总区域、经济分组、非主权地区 black_list = [ "世界", "北美", "东亚与太平洋地区", "欧洲与中亚地区", "拉丁美洲与加勒比海地区", "撒哈拉以南非洲地区", "南亚", "高收入国家", "低收入国家", "中等收入国家", "中高等收入国家", "阿鲁巴", "中国香港特别行政区", "中国澳门特别行政区", "波多黎各", "关岛", "格陵兰", "法罗群岛", "科索沃" ] # 过滤黑名单数据,重置索引 df = df[~df["Country Name"].isin(black_list)].reset_index(drop=True) print("清洗后剩余国家数量:", df["Country Name"].nunique())4.2 宽表转长表(数据重塑)
原始宽表一行对应一个国家,多年份横向排列,不适合时序轮播。使用pd.melt()将宽表转为长表,拆分出年份和人口单列。
python
运行
# 固定属性列:国家名称 attr_cols = ["Country Name"] # 筛选1960-2024所有年份列 year_cols = [str(y) for y in range(1960, 2025)] # 宽表转长表 df_long = pd.melt( df, id_vars=attr_cols, value_vars=year_cols, var_name="Year", value_name="Population" )4.3 数据类型修正与空值清理
年份转为整型、人口转为数值类型,并剔除空值数据,最终只保留国家名称、年份、人口三列核心字段。
python
运行
# 保留核心字段 df_clean = df_long[["Country Name", "Year", "Population"]] # 类型转换 df_clean["Year"] = df_clean["Year"].astype(int) df_clean["Population"] = pd.to_numeric(df_clean["Population"]) # 删除空值 df_clean.dropna(inplace=True) # 查看清洗后数据 df_clean.head()经过处理后,我们得到了结构规整、数据纯净的数据集,总计上万条有效记录,满足可视化要求。
五、可视化开发:从基础版到 B 站风格美化
5.1 单年份柱状图测试
先单独绘制某一年份的横向柱状图,验证绘图逻辑,这里以 1990 年为例,取人口 Top20 国家:
python
运行
# 筛选1990年数据并排序 test_df = df_clean[df_clean["Year"] == 1990] test_df = test_df.sort_values(by="Population", ascending=False).head(20) # 绘制横向柱状图 bar_test = ( Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK)) .add_xaxis(test_df["Country Name"].tolist()) .add_yaxis("人口", test_df["Population"].tolist()) .reversal_axis() # 反转坐标轴,制作横向柱状图 .set_global_opts(title_opts=opts.TitleOpts(title="1990年世界人口排名")) .set_series_opts(label_opts=opts.LabelOpts(position="right")) ) bar_test.render_notebook()基础图表渲染正常后,就可以结合Timeline时间组件,实现年份轮播效果。
5.2 基础版时间轮播图
遍历所有年份,为每一年生成独立柱状图,通过Timeline拼接成自动轮播动画,支持循环播放。
python
运行
# 获取所有年份列表 year_list = df_clean["Year"].unique().tolist() # 初始化时间线组件 timeline = Timeline(init_opts=opts.InitOpts(width="1500px", height="820px", theme=ThemeType.DARK)) # 遍历每一个年份生成柱状图 for year in year_list: data_df = df_clean[df_clean["Year"] == year] # 取人口前20国家,先降序再升序,配合轴反转实现排名从上到下递减 data_df = data_df.sort_values("Population", ascending=False).head(20) data_df = data_df.sort_values("Population", ascending=True) country = data_df["Country Name"].tolist() population = data_df["Population"].tolist() bar = ( Bar() .add_xaxis(country) .add_yaxis("人口", population) .reversal_axis() .set_global_opts( title_opts=opts.TitleOpts(title=f"{year}年世界人口排名"), legend_opts=opts.LegendOpts(is_show=False) # 隐藏图例 ) .set_series_opts(label_opts=opts.LabelOpts(position="right")) ) timeline.add(bar, str(year)) # 配置轮播规则:自动播放、600ms间隔、循环播放 timeline.add_schema(is_auto_play=True, play_interval=600, is_loop_play=True) # 生成网页文件 timeline.render("人口轮播_基础版.html")5.3 B 站风格深度美化(最终完整版)
基础版功能已实现,接下来进行视觉升级,复刻 B 站主流数据可视化风格:深色背景、动态配色、圆角柱子、精致时间轴。
核心优化点:
- 超大画布 + 纯黑背景,提升沉浸感;
- JS 代码实现柱子循环动态配色;
- 柱状图圆角、透明度优化;
- 自定义标签格式、时间轴样式;
- 强化交互视觉反馈。
python
运行
# 定义动态配色JS代码,不同排名显示不同颜色 color_js = JsCode(""" function(params){ let c = ['#ff4757','#ffa502','#fffa65','#2ed573','#1e90ff','#3742fa','#a55eea','#48dbfb']; return c[params.dataIndex % c.length]; } """) # 初始化最终版时间线,设置尺寸、深色背景 timeline_final = Timeline( init_opts=opts.InitOpts( width="1600px", height="850px", theme=ThemeType.DARK, bg_color="#080808" # 极深黑色背景 ) ) # 遍历年份绘图 for year in year_list: data_df = df_clean[df_clean["Year"] == year] data_df = data_df.sort_values("Population", ascending=False).head(20) data_df = data_df.sort_values("Population", ascending=True) country = data_df["Country Name"].tolist() population = data_df["Population"].tolist() bar = ( Bar() .add_xaxis(country) .add_yaxis( "人口", population, # 动态颜色、透明度、圆角 itemstyle_opts=opts.ItemStyleOpts( color=color_js, opacity=0.85, border_radius=7 ) ) .reversal_axis() .set_global_opts( title_opts=opts.TitleOpts(title=f"{year}年世界人口排名", pos_left="center"), legend_opts=opts.LegendOpts(is_show=False), # 悬浮提示框 tooltip_opts=opts.TooltipOpts(formatter="{b}<br>人口:{c} 人") ) # 标签格式化,显示单位 .set_series_opts(label_opts=opts.LabelOpts(position="right", formatter="{c}人", font_size=11)) ) timeline_final.add(bar, str(year)) # 美化时间轴样式 timeline_final.add_schema( is_auto_play=True, play_interval=600, is_loop_play=True, 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") ) # 输出最终成品HTML timeline_final.render("B站同款人口动态排行.html") timeline_final.render_notebook()六、项目成果展示
运行代码后,会生成可直接用浏览器打开的B站同款人口动态排行.html文件,成品具备以下效果: ✅ 1960-2024 年逐年自动轮播,Top20 国家人口实时排序; ✅ 深色 B 站风界面,彩色圆角柱状条,视觉效果精致; ✅ 支持播放 / 暂停、拖拽年份、鼠标悬浮查看人口三大交互; ✅ 数据纯净,无大洲、地区汇总等无效内容干扰。
打开网页静静观看六十多年人口变迁,能清晰看到各大人口大国位次的变化,数据故事感拉满。
七、项目总结与后续优化方向
7.1 项目总结
本次项目完整走完了数据读取→探查→清洗→格式转换→可视化→美化的标准数据分析全流程,核心难点有两个:
- 数据清洗:利用黑名单精准过滤汇总数据,保证数据源真实有效;
- 排序与坐标轴配合:先降序取 Top20、再升序排列,结合
reversal_axis()实现 “人口越多排名越靠上” 的视觉逻辑。
同时也吃透了pyecharts时间线组件、JS 动态配色、样式美化等实用技巧,可复用在 GDP、销量、榜单等各类动态排名场景中。
7.2 后续优化思路
- 增加国旗图标:通过 Base64 图片在国家名称旁搭配对应国旗,视觉效果更丰富;
- 多指标切换:增加下拉菜单,支持人口增长率、GDP 等多数据维度切换轮播;
- 性能优化:数据量庞大时,预缓存各年份 Top 数据,降低前端渲染压力;
- 导出视频:结合录屏工具,将 HTML 动态图表转为视频,直接发布到短视频平台。
八、写在最后
动态排名轮播图是 Python 数据分析入门到进阶的经典实战案例,既练习了pandas数据处理能力,又掌握了交互式可视化技巧。如果你也喜欢数据可视化,不妨拿着这份代码和数据集,动手修改指标、调整样式,打造属于自己的动态数据榜单吧!