【跟着SCI学作图】Matplotlib fill_between绘制折线图的置信区间

文摘   教育   2023-04-01 21:10   北京  


01 引言:

今天复现一下朋友发我了一张论文里的图表(原图如下所示),主要是Matplotlib的fill_between的知识点,作者在绘制图置信区间折线图的基础上,增加了一个子图,将数据与历史均值作差,直观明了的展示数据与历史均值的差异。

02 样例数据生产:

由于文章中未提供数据,这边我们借助numpy的random函数生成一个样例数据,20列对应2001-2020年,12行对应每年的12个月份。

np.random.seed(3)x = np.arange(1,13)df= pd.DataFrame()# 构造2001年的数据df['y2001'] = -2*x**2+5*x+np.random.rand(12)*np.random.rand(1)*100+500# 在2001年的数据基础上增加随机数构造剩余年份数据for i in range(2,21):    df['y'+str(2000+i)] = df['y2001']+np.random.rand(12)*np.random.rand(1)**2*100print(df)

03可视化数据:

图表中主要用到了均值和标准差数据,这边可以借助pandas的describe直接获取。

fig,axs = plt.subplots(2,1,figsize = (8,6))axs[0].plot(x,df['y2019'],color = 'r',marker = '.',label = '2019')axs[0].plot(x,df.T.describe().loc['mean'],color = 'k',marker = '.',label = 'mean')axs[0].fill_between(x,df.T.describe().loc['mean']-df.T.describe().loc['std'],df.T.describe().loc['mean']+df.T.describe().loc['std'],                    alpha = 0.3,color = 'k',label = 'std')axs[1].plot(x,df['y2019']-df.T.describe().loc['mean'],color = 'k')axs[1].axhline(y = 0,c = 'k')y1 ,y2 = df['y2019']-df.T.describe().loc['mean'],0axs[1].fill_between(x,y1 ,y2,where = (y2<y1),color = 'r',alpha = 1,interpolate = True,label = 'increase')axs[1].fill_between(x,y1 ,y2,where = (y2>y1),color = 'b',alpha = 1,interpolate = True,label = 'decrease')plt.show()

034完整代码如下:

# -*- encoding: utf-8 -*-'''@File    :   GZH0401.py@Time    :   2023/04/01 20:37:58@Author  :   HMX@Version :   1.0@Contact :   kzdhb8023@163.com'''
# here put the import libimport matplotlib as mplimport matplotlib.pyplot as pltimport numpy as npimport pandas as pd
size = 15fontdict = {'weight': 'normal','size':size,'color':'k','family':'SimHei'}mpl.rcParams.update( { 'text.usetex': False, 'font.family': 'stixgeneral', 'mathtext.fontset': 'stix', "font.family":'serif', "font.size": size, "mathtext.fontset":'stix', "font.serif": ['Times New Roman'], } )
np.random.seed(3)x = np.arange(1,13)df= pd.DataFrame()# 构造2001年的数据df['y2001'] = -2*x**2+5*x+np.random.rand(12)*np.random.rand(1)*100+500# 在2001年的数据基础上增加随机数构造剩余年份数据for i in range(2,21): df['y'+str(2000+i)] = df['y2001']+np.random.rand(12)*np.random.rand(1)**2*100print(df)print(df.T.describe())
# 绘制fig,axs = plt.subplots(2,1,figsize = (8,6))axs[0].plot(x,df['y2019'],color = 'r',marker = '.',label = '2019')axs[0].plot(x,df.T.describe().loc['mean'],color = 'k',marker = '.',label = 'mean')axs[0].fill_between(x,df.T.describe().loc['mean']-df.T.describe().loc['std'],df.T.describe().loc['mean']+df.T.describe().loc['std'], alpha = 0.3,color = 'k',label = 'std')axs[1].plot(x,df['y2019']-df.T.describe().loc['mean'],color = 'k')axs[1].axhline(y = 0,c = 'k')y1 ,y2 = df['y2019']-df.T.describe().loc['mean'],0axs[1].fill_between(x,y1 ,y2,where = (y2<y1),color = 'r',alpha = 1,interpolate = True,label = 'increase')axs[1].fill_between(x,y1 ,y2,where = (y2>y1),color = 'b',alpha = 1,interpolate = True,label = 'decrease')
# 完善一下细节titles = ['(a)','(b)']for j,iax in enumerate(axs): iax.set_ylabel('森气笔记',fontdict = fontdict) iax.set_xticks(x) iax.legend(loc='lower left',frameon = False) iax.set_title(titles[j]+' ',loc= 'right',y = 0.82,fontsize =size)axs[1].set_xticklabels(["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"])axs[0].set_xticklabels([])axs[1].set_xlabel('Month')axs[0].set_ylim(300,600)axs[1].set_ylim(-30,30)axs[1].set_yticks(np.arange(-30,31,15))
plt.tight_layout()plt.savefig(r'D:\ForestMeteorology\GZH230401\data\GZH0401.png',dpi = 600)plt.show()

欢迎私交流学习


戳这里关注我

请点赞、在看、关注,你们的支持是我更新的动力。

森气笔记
记录分享森林气象学相关的Python GEE Arcgis QGIS Matlab等学习笔记