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

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

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*100
print(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'],0
axs[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()

请添加图片描述

04 完整代码如下:

# -*- 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 lib
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

size = 15
fontdict = {'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*100
print(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'],0
axs[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()

以上就是本期推文的全部内容了,如果对你有帮助的话,请‘点赞’、‘收藏’,‘关注’,你们的支持是我更新的动力。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值