首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >超动感,百行Python代码制作动态气泡图

超动感,百行Python代码制作动态气泡图

作者头像
lyhue1991
发布2021-06-15 10:05:49
1.1K1
发布2021-06-15 10:05:49
举报

先上图片:

再上视频:

最后上代码:

import numpy as np 
import pandas as pd 
from matplotlib import pyplot as plt 
import matplotlib.animation as  animation 

import imageio
import os 
import cv2
from PIL import Image


plt.rcParams['animation.writer'] = 'html'
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

def html_to_gif(html_file, gif_file, duration=0.1):
    path = html_file.replace(".html","_frames")
    images = [os.path.join(path,x) for x in sorted(os.listdir(path))]
    frames = [imageio.imread(x) for x in images]
    imageio.mimsave(gif_file, frames, 'gif', duration=duration)
    return gif_file

cmap = [
'#2E91E5',
'#1CA71C',
'#DA16FF',
'#B68100',
'#EB663B',
'#00A08B',
'#FC0080',
'#6C7C32',
'#862A16',
'#620042',
'#DA60CA',
'#0D2A63']*100

dfx = pd.read_csv("./data/gdp_per_capita.csv")
dfx = dfx.set_index("year")
dfx.index = [str(x) for x in dfx.index]
dfx = dfx[sorted(dfx.columns)]

dfy = pd.read_csv("./data/life_expect.csv")
dfy = dfy.set_index("year")
dfy.index = [str(x) for x in dfy.index]
dfy = dfy[sorted(dfy.columns)]

dfz = pd.read_csv("./data/pop_amount.csv")
dfz = dfz.set_index("year")
dfz.index = [str(x) for x in dfz.index]
dfz = dfz[sorted(dfz.columns)]

def bubble_chart_race(dfx,dfy,dfz,title = "中国大陆各省市历年人均GDP和预期寿命变化",
                      filename = None,
                      figsize = (6.5,3.5),dpi = 144,
                      duration = 0.5,
                      xlabel = "人均GDP(人民币)",
                      ylabel = "预期寿命", 
                      size_label = "点尺寸: 人口数量",
                      anotate_points = ["江西省","北京市","上海市","广东省",
                                        "河南省","江苏省","黑龙江省","西藏自治区"]):

    fig,ax = plt.subplots(figsize=figsize,dpi=dpi)

    ax.set_facecolor("0.9")
    ax.set_title(title,color = "black",fontsize = 12)

    # 调整spines
    ax.spines["top"].set_visible(False)
    ax.spines["right"].set_visible(False)
    ax.spines["left"].set_visible(False)
    ax.spines["bottom"].set_visible(False)

    def plot_frame(date):
        
        dfdata = pd.DataFrame() 
        xdata = dfx.loc[date,:].sort_index() 
        ydata = dfy.loc[date,:].sort_index()
        zdata = dfz.loc[date,:].sort_index()
        dfdata["x"] = xdata
        dfdata["y"] = ydata
        dfdata["z"] = zdata 

        # 绘制散点图像
        
        ax.clear()
        ax.scatter(dfdata["x"],dfdata["y"],s = 100*dfdata["z"]/dfdata["z"].mean(),
               c = (cmap*100)[0:len(dfdata)],alpha = 0.5)


        # 添加图例文字
        for i,p in enumerate(dfdata.index):
            px,py,pz = dfdata.loc[p,["x","y","z"]].tolist() 
            if p in anotate_points:
                ax.annotate(p,xy = (px,py),  xycoords = "data",
                    xytext = (-15,10),fontsize = 10,fontweight = "bold",color = cmap[i], textcoords = "offset points")

        ax.tick_params(bottom = False,left = False,labelsize = 8,direction = "in",length = 2)

        # 调整绘图范围
        xlim = (dfx.values.min(),dfx.values.max())
        ax.set_xlim(left = xlim[0]-(xlim[1]-xlim[0])/10,right = xlim[1]+(xlim[1]-xlim[0])/10)
        ylim = (dfy.values.min(),dfy.values.max())
        ax.set_ylim(bottom = ylim[0]-(ylim[1]-ylim[0])/10,top = ylim[1]+(ylim[1]-ylim[0])/5)


        # 添加辅助元素
        ax.text(0.5, 0.5, date, va="center", ha="center",alpha=0.3, size = 50,transform = ax.transAxes)
        ax.text(0.85, 0.92, size_label, ha="center",va="center", size = 10,transform = ax.transAxes)

        ax.grid(axis = "x",color="white",lw=1,ls = "-")
        ax.tick_params(bottom = False,left = False,labelsize = 8,direction = "in",length = 2)
        ax.set_xlabel(xlabel,fontsize = 10)
        ax.set_ylabel(ylabel,fontsize = 10)
    
    
    bubble_animation = animation.FuncAnimation(fig,plot_frame,frames = dfx.index ,interval = int(duration*1000))
    if filename is None:
        try:
            from IPython.display import HTML
            return HTML(bubble_animation.to_jshtml())
        except ImportError:
            pass
    else:
        bubble_animation.save(filename)
        return filename


html_file = "bubble_chart_race.html"
gif_file = html_file.replace(".html",".gif")
bubble_chart_race(dfx,dfy,dfz,filename = html_file,title = "中国大陆各省份历年人均GDP和预期寿命")

html_to_gif(html_file,gif_file,duration=1.0)

主要思路是构建plot_frame函数逐帧绘制图像,再用matplotlib的animation模块制作动画。

收工。?

打码不易,喜欢本篇的小伙伴,或者需要完整代码和绘图数据集的同学,可以对本文点赞,在看,和分享后在公众号“算法美食屋”后台回复关键字:动态图,添加作者微信获取。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-05-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 算法美食屋 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
图数据库 KonisGraph
图数据库 KonisGraph(TencentDB for KonisGraph)是一种云端图数据库服务,基于腾讯在海量图数据上的实践经验,提供一站式海量图数据存储、管理、实时查询、计算、可视化分析能力;KonisGraph 支持属性图模型和 TinkerPop Gremlin 查询语言,能够帮助用户快速完成对图数据的建模、查询和可视化分析。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档