使用循环创建具有双 y 轴的多个 matplotlib 图

Using loops to create multiple matplotlib graphs with dual y-axes

我正在尝试使用 matplotlib 创建许多时间序列图,以使用循环来销售不同种类的水果及其平均销售价格。每个图表都具有以下相同的特征:

  • 左侧 y 轴的售价(收益率),右侧 y 轴的每日销售量(ADV)
  • x 轴上的时间(月)
  • 标有每个 y 轴系列的图表标题
  • 阴影(代表预测)
  • 垂直参考线(代表业务规则的变化)

这是一个示例:

enter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
plt.style.use('seaborn-whitegrid')

# Set figure Size
fig.set_figwidth(8)
fig.set_figheight(6)

x_col ="date"
title=['Apple Metrics: ADV and Yield Over Time','Banana Metrics: ADV and Yield Over Time','Pear Metrics: ADV and Yield Over Time']
y1_col = ["apple_yld","banana_yld","pear_yld"]
y2_col = ["apple_adv","banana_adv","pear_adv"]
start_date='2015-01-01'
end_date='2021-12-01'
start_date_of_shading='2020-06-01'
end_date_of_shading='2023-05-01'


for x_col in y1_col and y2_col:

# Graph title
    fig.suptitle(title,fontsize=20)

# set x label which is common / set left y-axis label / set labelcolor and labelsize to the left Y-axis
    mygraph.set_xlabel('Date (Monthly Frequency)')
    mygraph.set_ylabel('Yield (inverted scale)', color='red',size='x-large')
    mygraph.tick_params(axis='y', labelcolor='red', labelsize='large')

# plot fruit Yield on left Y-axis; invert axis
    mygraph.plot(df2[x_col], df2[y1_col], color='red',linewidth=3.0)
    mygraph.invert_yaxis()
    mygraph.yaxis.set_major_formatter(mpl.ticker.StrMethodFormatter('{x:,.2f}'))
    mygraph.axvline(pd.Timestamp('2019-06-01'),color='green', linestyle='--',linewidth=4.0)  

# twinx sets the same x-axis for both plots / set right y-axis label / set labelcolor and labelsize to the right Y-axis
    mygraph_1 = mygraph.twinx()
    mygraph_1.set_ylabel('ADV', color='blue', size='x-large')
    mygraph_1.tick_params(axis='y', labelcolor='blue',labelsize='large')
    mygraph.set_xlim(['2015-01-01','2019-12-01'])

# plot fruit ADV on right Y-axis, format with comma separator  
    mygraph_1.plot(df2[x_col], df2[y2_col], color='blue',linewidth=3.0)
    mygraph_1.yaxis.set_major_formatter(mpl.ticker.StrMethodFormatter('{x:,.0f}'))
    plt.show()

您可以使用 plt.subplots(),它返回一个图形和轴对象的元组。在这种特殊情况下,轴将是一个形状数组(行 x 列)。您可以将每个项目分配到适当的轴位置,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
rows=len(y1_col) #set the desired number of rows
cols=2 #set the desired number of columns

fig, ax = plt.subplots(rows, cols, figsize=(13,8),sharex=False,sharey=False) # if you want to turn off sharing axis.
row=0 #to iterate over rows/cols
col=0 #to iterate over rows/cols
for item_num in range(len(y1_col)):

    ax[row][col].plot(df2[x_col], df2[y1_col[item_num]], color='red',linewidth=3.0)
    ax[row][col].set_xlabel('Date (Monthly Frequency)')
    ax[row][col].set_ylabel('Yield (inverted scale)', color='red',size='x-large')
    ax[row][col].tick_params(axis='y', labelcolor='red', labelsize='large')
    ax[row][col].invert_yaxis()
    ax[row][col].yaxis.set_major_formatter(mpl.ticker.StrMethodFormatter('{x:,.2f}'))
    ax[row][col].axvline(pd.Timestamp('2019-06-01'),color='green', linestyle='--',linewidth=4.0)  


    axp = ax[row][col].twinx()
    axp.plot(df2[x_col], df2[y2_col[item_num]], color='blue',linewidth=3.0)
    axp.set_ylabel('ADV', color='blue', size='x-large')
    axp.tick_params(axis='y', labelcolor='blue',labelsize='large')
    axp.set_xlim(['2015-01-01','2019-12-01'])


    col=col+1
    if col==1:
        row=row
    else:
        row=row+1
        col=0

plt.show()