详解用 matplotlib 绘制动态条形图

2023-11-06

详解用 matplotlib 绘制动态条形图

端午安康!

近日看到联合国网站提供的世界人口数据集,其中一个子数据集包含了各国 1950-2015年的人口数据。

假日值班,有自由的时间,就基于这个数据集,用 matplotlib 实现了一个世界人口 66 年变化的动态条形图。

最后的 gif 图:

动态条形图
下面把实现的主要步骤记录下来。原始数据、详细的源代码请到 QQ群:python草堂,457079928 下载,有问题也可以到那里讨论。

数据集介绍

‘population_estimates.csv’ ,逗号分隔符,utf-8编码,csv格式。

18018 rows × 4 columns

有4 个字段:

  • Region,国家和地区的英文名称;
  • Country Code,国家和地区的代码;
  • Year,4位数的年份;
  • Population,人口数,单位:千人。

不仅有各个国家的人口数据,还包括大的地区的人口统计数据,如世界总人口,亚洲、东亚、北美洲等。
在这里插入图片描述

导入用到的库

%matplotlib inline

import pandas as pd
import numpy as np
import pprint
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.animation as animation
from IPython.display import HTML
import matplotlib.colors as colors

数据清洗

我想制作2015年人口最多的10个国家,66年人口变化的动态条形图。所以,

我需要对数据做如下处理:

  1. 提取其中226个国家的历年人口数据;
  2. 提取2015年人口最多的10个国家的名称;
  3. 提取2015年人口最多的10个国家的历年人口数据;
  4. 有些国家的名称有点长,弄短一点;
  5. 在两个用到的数据集中,美国的名称不一致,统一下。

为了提取其中226个国家的历年人口数据,我找到一个226个国家的中、英文名称对照表,Countries_Name.csv,格式同上

读入数据文件

读入世界人口数据:

pe = pd.read_csv('population_estimates.csv',
                 #usecols=['Region','Year','Population'],
                 dtype={'Region':str,'Year':int,'Population':float}
                )

pe, population_estimates 的首字母缩写。

读入国家名称中英文数据:

ct = pd.read_csv('Countries_Name.csv')

ct  # countries

在这里插入图片描述
由于在两个数据集中美国的英文名称不一致,在这个数据集中是:‘United States of America’,而在国家名称数据表中是:'United States’。需要先将两个数据集中统一为:'United States’。

合并两个数据集

由于两个数据集中的国家不完全一致,最后得到193个主权国家的历年人口数据。
在这里插入图片描述
由于俄罗斯的英文全称是 ‘Russian Federation’,长了点,我把它替换为’Russian’,以便在动态条形图中显示。

提取2015年人口 top10 国家的名称

提取2015年人口 top10 国家的名称,并将它们存为列表备用。

['China',
 'India',
 'United States',
 'Indonesia',
 'Brazil',
 'Pakistan',
 'Nigeria',
 'Bangladesh',
 'Russian',
 'Japan']

生成 Top10 国家的历年人口数据

pe_ct_top10 = pe_ct[pe_ct['Region'].isin(top10_region)].sort_values('Population',ascending=True)

pe_ct_top10

在这里插入图片描述
10 个国家,66年的人口数据。

绘制10个国家2015年的静态条形图

fig, ax = plt.subplots(figsize = (15, 10))

ax.clear()

df_2015 = pe_ct_top10[pe_ct_top10.Year == 2015].sort_values('Population',ascending=False)

x = df_2015['Region']
y = df_2015['Population']
cn = df_2015['CNName'].values.tolist()
cvalues = list(colors.TABLEAU_COLORS.values())

eb = ax.barh(x, y, color= cvalues)
   
for b in eb:
    if b.get_width() < y.mean():
        alpha = b.get_width()/y.mean()
    else:
        alpha = 1.0        
    b.set_alpha(alpha)

dx = y.max()/200

for i, (p, r, c) in enumerate(zip(y, x, cn)):
    
    ax.text(p-dx, i, r, size=12, weight=400, ha='right', va='bottom')
    ax.text(p-dx, i-.25, c, 
            fontproperties='SimHei',
            size=12, ha='right', va='baseline')
    ax.text(p+dx, i, f'{p/10:,.0f}', size=12, ha='left', va='center',family='Arial')
    
ax.text(1, 0.4, 2015, transform=ax.transAxes, color='#777777', size=46, ha='right', weight=900)
ax.text(0, 1.07, 'Population (thousands)', transform=ax.transAxes, size=12, color='#777777')

ax.xaxis.set_major_formatter(ticker.StrMethodFormatter('{x:,.0f}'))
ax.xaxis.set_ticks_position('top')

ax.tick_params(axis='x', colors='#777777', labelsize=12)
ax.set_yticks([])
ax.margins(0, 0.01)
ax.grid(which='major', axis='x', linestyle='--')
ax.set_axisbelow(True)

fig.suptitle('2015年世界人口最多的国家',fontsize=24, 
             weight=600, family='SimHei')

plt.box(False)

在这里插入图片描述

封装为函数

将上面绘制条形图的代码封装为函数:

def dynamic_bar(year):
    
    df_year = pe_ct_top10[pe_ct_top10.Year == year].sort_values('Population',ascending=False)
    
    ax.clear()
    #ax.set_xlim([1000, pe_ct_top10['Population'].max()])
 
    x = df_year['Region']
    y = df_year['Population']
    cn = df_year['CNName'].values.tolist()
    cvalues = list(colors.TABLEAU_COLORS.values())
    
    eb = ax.barh(x, y)
    
    for b in eb:
        if b.get_width() < y.median():
            facecolor = '#ff7f0e'
            alpha = b.get_width()/y.median()*0.5
        else:
            facecolor = '#1f77b4'
            alpha = b.get_width()/y.max()        
        
        b.set_alpha(alpha)
        b.set_color(facecolor)
    
    dx = y.max()/200
    
    for i, (p, r, c) in enumerate(zip(y, x, cn)):
        ax.text(p-dx, i, r, size=12, weight=400, ha='right', va='bottom')
        ax.text(p-dx, i-.25, c,
                family='SimHei',
                size=12, ha='right', va='baseline')
        ax.text(p+dx, i, f'{p/10:,.0f}', size=12, 
                ha='left', va='center',family='Arial')
       
    ax.text(1, 0.4, year, transform=ax.transAxes, color='#777777', 
            size=46, ha='right', weight=900)
    ax.text(0, 1.07, 'Population (thousands)', 
            transform=ax.transAxes, size=12, color='#777777')
    
    ax.xaxis.set_major_formatter(ticker.StrMethodFormatter('{x:,.0f}'))
    ax.xaxis.set_ticks_position('top')
    
    ax.tick_params(axis='x', colors='#777777', labelsize=12)
    ax.set_yticks([])
    ax.margins(0, 0.01)
    
    ax.grid(which='major', axis='x', linestyle='--')
    ax.set_axisbelow(True)
    
    fig.suptitle('人口 TOP10 国家1950-2015年的人口变化', fontsize=24, weight=500, family='SimHei')

    plt.box(False)

生成动图

fig, ax = plt.subplots(figsize = (15, 8))

popu_growth = animation.FuncAnimation(fig, dynamic_bar, 
                                   frames=range(pe_ct_top10['Year'].min(), pe_ct_top10['Year'].max()))

HTML(popu_growth.to_jshtml())

在我的 jupyterlab 中就会输出如下带控制器的动图:
在这里插入图片描述

将动图保存为gif

popu_growth.save('popu_growth.gif', writer='pillow')

就会在代码主文件所在目录下生成一个 gif 图:

说明:

  1. 我以中位数为分割,大于中位数的颜色相同,用alpha变化表达与最大值的比较;
  2. 小于中位数的颜色相同,用alpha变化表达与中位数的比较;
  3. 请注意观察中位数国家的变化、印度人口与中国人口的变化比较;
  4. 俄罗斯人口在不同时期的较大变化;

在这里插入图片描述

很幸运,该 gif 文件接近,但没有超过 5 M,能够传上来。

你可以根据需要观察不同国家的人口变化。

原始数据、完整的 ipynb 文件请移步 python草堂,457079928 下载。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

详解用 matplotlib 绘制动态条形图 的相关文章

随机推荐

  • vue中手机号码+座机号码、邮箱正则校验规则封装

    直接上代码 封装验证器 export function isvalidPhone phone const isPhone 1 38 0 9 4 014 9 59 0 35 9 6 2567 7 0 8 d 8 11位合法手机号码 const
  • TI(德州仪器) TMS320C674x逆向分析之二

    TI官网文档 http www ti com product tms320c6745 technicaldocuments 里面资料非常详细 可以对着里面一个个看 用的比较多的两个文档 TMS320C674x指令格式 TMS320C674x
  • 【linux kernel】记一次linux内核裁剪总结

    记一次linux内核裁剪总结 一 背景 在linux内核构建过程中 根据实际应用场景 小生构建了一个大约5 7M大小的linux内核zImage镜像 发现其稍微有点大了 想着将其裁剪和缩小 于是乎对linux内核进行裁剪 本篇文章主要记录一
  • 谷歌浏览器ajax警告,ajax请求的问题,谷歌浏览器的警告提示Provisional headers are shown...

    不太了解百度后台是什么情况 我也只是做一个简单的搜索功能用了跨域 我看数据请求成功了 数据已经返回 但是谷歌浏览器总是出现这种情况 友情提示 愿意回答的大神就请帮着看看 不愿意帮助的也请别乱踩 别干缺德事 还有就是我在hbulider下面打
  • VNC unable to connect via 127.0.0.1:1080

    VNC远程登录出现自己电脑拒绝的时候 请查看一下自己是否设了代理登录之类的操作 这里是WIN 10 登录远程一台WIN 10 服务器 跟服务器设置没有什么关系 主要由于本地配置导致的 解决方案 File里面选择属性 取消代理设置即可 折腾了
  • WebTransport 开播的应用实践之路

    动手点关注 干货不迷路 Web开播的业务挑战 无论是本地软件推流还是Web推流 都需要解决推流抖动 画面高糊 音频卡顿等问题 在现有的Web技术环境下 如何稳定地把高质量的音视频流呈现给更多用户 是我们技术团队攻克的重点 从技术角度来解读一
  • Hashtable和HashMap、ConcurrentHashMap 之间的区别

    Hashtable和HashMap的区别 HashMap和Hashtable都是哈希表数据结构 但是Hashtable是线程安全的 HashMap是线程不安全的 Hashtable实现线程安全就是简单的把关键方法都加上了synchroniz
  • 企业项目实战----CDN加速的实现

    前言 CDN加速对企业非常重要 体现在哪呢 举个例子 A企业的后端服务器在杭州 用户遍布全国 让全国的用户都去访问企业A在杭州的后端服务器你觉得可行吗 肯定不可行呀 第一 后端服务器承受不了全国这么巨大的访问量 第二 访问速度慢 要经过的陆
  • 提升职场价值,把握成长方向

    来自 IT人的职场进阶 同样的职场起点 为什么几年后大家差距很大 如果想快速升职加薪 有什么好方法吗 如何才能做到持续且快速的成长 这些疑惑都离不开一个本质问题 职场价值 因为企业用人的核心出发点是 你能否为企业创造价值 你的价值和薪酬职级
  • MSP430 EEPROM-24C512使用总结及代码说明

    MSP430 EEPROM 24C512使用总结及代码说明 https wenku baidu com view 61f407d6f705cc175527094b html
  • hooks中useMemo和useCallback详解

    要想学习useMemo必须要先知道React memo 这两者都有一定的优化作用 memo的作用 当数据变化时 代码会重新执行一遍 但是子组件数据没有变化也会执行 这个时候可以使用memo将子组件封装起来 让子组件的数据只在发生改变时才会执
  • sudo rosdep init ERROR: cannot download default sources list from:

    在sudo rosdep init时出现的错误ERROR cannot download default sources list from https raw githubusercontent com ros rosdistro mas
  • 安装一个虚拟服务器,一个云服务器可以装虚拟机么

    一个云服务器可以装虚拟机么 内容精选 换一换 虚拟IP地址用于为网卡提供第二个IP地址 同时支持与多个云服务器的网卡绑定 从而实现多个云服务器之间的高可用性 登录管理控制台 单击管理控制台左上角的 选择区域和项目 选择 计算 gt 云耀云服
  • WEB前端命名规范

    https www cnblogs com ysx215 p 7461777 html
  • 数组指针 行指针 列指针

    概念 我们把指向数组的指针叫做数组指针 后面还会学到指针数组 这两个是不一样的 根据中学语文偏正词组的知识可以知道 前者是指针 后者是数组 一般指针变量 int a 2 3 1 2 3 4 5 6 int P a 0 0 int p a 0
  • 短视频账号矩阵系统如何技术嵌入Chatgpt?

    将GPT Generative Pre trained Transformer 嵌入短视频账号矩阵系统需要以下步骤 1 获取GPT模型 可以自行训练或使用开源的预训练模型 如GPT 2 GPT 3等 2 导入GPT模型 将GPT模型导入到短
  • Metronic学习-1-替换google字体,让页面打开更流畅

    Metronic是一款强大的后台模板 包括很多组件 接触过很多后台模板 有Layui AdminLTE Inspinia hui 感觉Layui适合快速开发 Layui封闭性很强 对于前端不太熟悉的话 只能按模仿 如果需要深入学习 需要花费
  • Html-根据不同的分辨率设置不同的背景图片

    media only screen and min width 1024px 当分辨率width gt 1024px 时使用1 jpg作为背景图片 bg background url images 1 jpg no repeat media
  • Reactor模型与Proactor模型

    1 Reactor模型 1 1 什么是Reactor模式 它是基于IO多路复用与线程池 Reactor模式的核心组成部分包括Reactor和处理资源池 进程池或线程池 Reactor负责监听和分配事件 处理资源池负责处理事件 Reactor
  • 详解用 matplotlib 绘制动态条形图

    详解用 matplotlib 绘制动态条形图 端午安康 近日看到联合国网站提供的世界人口数据集 其中一个子数据集包含了各国 1950 2015年的人口数据 假日值班 有自由的时间 就基于这个数据集 用 matplotlib 实现了一个世界人