Python-Matplotlib 动态柱形图绘制(数据分享)

2021-02-22 11:42:30 浏览数 (1)

这期开始,我们将公众号刚开始的不成熟风格文章推文改成与现在相统一的风格,同时也为了解决大家复制不了代码的问题,本期推文,将介绍使用Python-matplotlib 绘制动态柱形图的教程推文,主要涉及的知识点如下:

  • matplotlib的animation模块制作动态图
  • ticker的定制化操作
  • 自定义图例的添加
  • 练习数据分享

animation模块制作动态图

在之前的推文中有转载过优秀的Python第三方包绘制动态图,可以做到使用较少的代码绘制出优秀的动态图表。但小编的建议是,若想系统的学习可视化绘制,还是从基础的图表开始,这样可以使你熟悉绘图函数;但若只为了制作出动态图,则可以考虑使用优秀的集成包。

预览数据

读取数据的代码如下:

代码语言:javascript复制
gapminder = pd.read_csv(r'gapminderDataall.csv',
                        usecols=['name','time','population','region'])
gapminder['time'] = gapminder['time'].apply(lambda x : int(x))
gapminder.head()

预览效果如下(部分):

静态柱形图绘制

在绘制动态图表之前,我们需要单独绘制一幅静态图表用于查看数据的分布情况及可能需要修改的图表元素。这里,我们选取一年的数据进行柱形图的绘制,具体绘制代码如下:

代码语言:javascript复制
current_test = 2015
current_data = (gapminder[gapminder['time'].eq(current_test)]
               .sort_values(by='population',ascending = False).head(12))
fig, ax = plt.subplots(figsize = (12, 7),dpi=150)
ax.barh(current_data['name'],current_data['population'])
ax.text(.83,-.06,'nVisualization by DataCharm',transform = ax.transAxes,
        ha='center', va='center',fontsize = 9,color='black')

plt.savefig(r'Bar_chart_rance_single_year_pir.png',
            width=5,height=7,dpi=900,bbox_inches='tight')

可视化结果如下:

可以看出,默认的出土效果存在很大不足:

  1. 默认颜色没灵魂
  2. 轴脊、刻度等图表元素还有很大提升空间

图表美化

接下来,我们灵活设置图表属性,使其颜值提升:我们直接给出代码:

代码语言:javascript复制
colors_region = dict(zip(
    ['Asia', 'Africa', 'Europe', 'The Americas'],
    ['#FF798E','#33DDED','#FFEC33','#99EF33']
))

region_color = gapminder.set_index('name')['region']
region_color_dic = gapminder.set_index('name')['region'].to_dict()

#可视化操作
plt.rcParams['font.family'] = ['Roboto Mono']
fig, ax = plt.subplots(figsize = (12,7),dpi = 150)
#将数据反转
current_data = current_data[::-1]
dx = current_data['population'].max()/200000
ax.barh(current_data['name'],current_data['population'],
        color = [colors_region[region_color_dic[x]] for x in current_data['name']])
#添加标签
for i, (value, name) in enumerate(zip(current_data['population'],current_data['name'])):
    ax.text(value - dx,i, name, ha="right")# 如:china:国家名
    ax.text(value - dx,i - .3, region_color_dic[name],ha="right")#地区名:如Asia
    ax.text(value   dx, i,f'{value/1000:,.0f}k',
        color=colors_region[region_color_dic[name]],ha = 'left', va = 'center',
        fontweight = 'bold',size = 12)
    #或者如下:
#   ax.text(value   100, i,'{:,.0f}k'.format(value),
#           color=colors_region[region_color_dic[name]],ha = 'left', va = 'center',
#           fontweight = 'bold',size = 12)
#添加年份标签
ax.text(1, .5, current_test, transform = ax.transAxes, size =120, ha = 'right',
        color="gray",alpha=.5,fontfamily = "Franklin Gothic Book" )

#修改网格等
#刻度标签形式
#ax.xaxis.set_major_formatter(ticker.StrMethodFormatter('{x/10**3:,.0f}k'))
#这里修改成另外一种形式
tick_f = lambda x, pos: f'{x/10**3:,.0f}K'
ax.xaxis.set_major_formatter(FuncFormatter(tick_f))
ax.xaxis.set_ticks_position('top')

ax.tick_params(axis='x',colors = 'gray',labelsize = 15,top=False,bottom = False)
ax.set_yticks([])
#ax.xaxis.set_major_locator(MultipleLocator(250000000))
ax.margins(0,0.01)
ax.grid(which='major',axis = 'x',ls='-')
ax.set_axisbelow(True)

ax.text(1,-0.02,'byNinghaitao',transform = ax.transAxes,color ='gray',ha = 'right')
ax.text(0,1.1,'Population (thousands)',transform = ax.transAxes,
            color ='gray',ha = 'left',)
#添加图例,自己定义
labels = list(colors_region.keys())
handles = [plt.Rectangle((0,0),1,1, color=colors_region[label]) for label in labels]
bar_legend = plt.legend(handles, labels, loc='lower right', title='Region',
                        fontsize=12,framealpha = .5)
# Put a nicer background color on the legend. 
#bar_legend.get_frame().set_facecolor('#00FFCC') 
bar_legend.get_title().set_fontsize(fontsize = 15)
plt.box(False)

代码中都有详细的解释,大家应该都是可以看懂的,这里列出比较重要的几个点:

  • 使用颜色字典给文本等熟悉附上颜色
代码语言:javascript复制
#添加标签
for i, (value, name) in enumerate(zip(current_data['population'],current_data['name'])):
    ax.text(value - dx,i, name, ha="right")# 如:china:国家名
    ax.text(value - dx,i - .3, region_color_dic[name],ha="right")#地区名:如Asia
    ax.text(value   dx, i,f'{value/1000:,.0f}k',
        color=colors_region[region_color_dic[name]],ha = 'left', va = 'center',
        fontweight = 'bold',size = 12)
  • 刻度样式的绘制
代码语言:javascript复制
ax.text(value   dx, i,f'{value/1000:,.0f}k',
ax.text(value   100, i,'{:,.0f}k'.format(value),
#           color=colors_region[region_color_dic[name]],ha = 'left', va = 'center',
#           fontweight = 'bold',size = 12)
  • 单独图例的添加

matplotlib 在定制化图例时没有ggplot2那么方便,往往需要单独绘制,这里绘制代码如下:

代码语言:javascript复制
            color ='gray',ha = 'left',)
#添加图例,自己定义
labels = list(colors_region.keys())
handles = [plt.Rectangle((0,0),1,1, color=colors_region[label]) for label in labels]
bar_legend = plt.legend(handles, labels, loc='lower right', title='Region',
                        fontsize=12,framealpha = .5)
# Put a nicer background color on the legend. 
#bar_legend.get_frame().set_facecolor('#00FFCC') 
bar_legend.get_title().set_fontsize(fontsize = 15)

最终可视化效果如下:

动态可视化绘制

接下来,我们就使用animation模块进行动态可视化绘制,直接给出完整的绘图代码:

代码语言:javascript复制
import pandas as pd
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import matplotlib.ticker as ticker
from matplotlib.ticker import FuncFormatter, MultipleLocator
from IPython.display import HTML

gapminder = pd.read_csv(r'gapminderDataall.csv',
                        usecols=['name','time','population','region'])
gapminder['time'] = gapminder['time'].apply(lambda x : int(x))

#颜色字典
colors_region = dict(zip(
    ['Asia', 'Africa', 'Europe', 'The Americas'],
    ['#FF798E','#33DDED','#FFEC33','#99EF33']
))
#地区字典
region_color_dic = gapminder.set_index('name')['region'].to_dict()

plt.rcParams['font.family'] = ['Roboto Mono']
plt.rcParams['animation.embed_limit'] = 2**64

fig, ax = plt.subplots(figsize = (12,7),dpi = 150)
def barh_animation(current_test):
    #current_test = 2013
    current_data = (gapminder[gapminder['time'].eq(current_test)]
                   .sort_values(by='population',ascending = True).tail(12))
    ax.clear()
    dx = current_data['population'].max()/200000
    ax.barh(current_data['name'],current_data['population'],
            color = [colors_region[region_color_dic[x]] for x in current_data['name']])
    #添加标签
    for i, (value, name) in enumerate(zip(current_data['population'],current_data['name'])):
        ax.text(value - dx,i, name, ha="right")# 如:china:国家名
        ax.text(value - dx,i - .3, region_color_dic[name],ha="right")#地区名:如Asia
        ax.text(value   dx, i,f'{value/1000:,.0f}k',
            color=colors_region[region_color_dic[name]],ha = 'left', va = 'center',
            fontweight = 'bold',size = 12)
    #添加年份标签
    ax.text(1, .5, current_test, transform = ax.transAxes, size =120, ha = 'right',
            color="gray",alpha=.5,fontfamily = "Franklin Gothic Book" )

    #修改网格等
    #刻度标签形式
    #这里修改成另外一种形式
    tick_f = lambda x, pos: f'{x/10**3:,.0f}K'
    ax.xaxis.set_major_formatter(FuncFormatter(tick_f))
    ax.xaxis.set_ticks_position('top')
    ax.tick_params(axis='x',colors = 'gray',labelsize = 15,top=False,bottom = False)
    ax.set_yticks([])
    ax.margins(0,0.01)
    ax.grid(which='major',axis = 'x',ls='-')
    ax.set_axisbelow(True)

    ax.text(1,-0.02,'byNinghaitao',transform = ax.transAxes,color ='gray',ha = 'right')
    ax.text(0,1.1,'Population (thousands)',transform = ax.transAxes,
                color ='gray',ha = 'left',)
    #添加图例
    labels = list(colors_region.keys())
    handles = [plt.Rectangle((0,0),1,1, color=colors_region[label]) for label in labels]
    bar_legend = plt.legend(handles, labels, loc='lower right', title='Region',
                            fontsize=12,framealpha = .5)
    bar_legend.get_title().set_fontsize(fontsize = 15)
    plt.box(False)
   # return fig   
#barh_animation(2018)

barh_animator = animation.FuncAnimation(fig,barh_animation, frames=np.arange(1800,2021))
HTML(barh_animator.to_jshtml())

「最终的动态效果如下视频所示:」

总结

动态图表的绘制在于更好的熟悉绘图函数和图层属性,希望可以帮助到你,此外,为了更好的练习,我们免费提供练习数哦,获取方式如下:

0 人点赞