子图子图

Subplotting subplots

我正在使用 matplotlib 创建两个图,每个图都是一个子图,在同一轴上显示两个指标。

我正在尝试 运行 它们显示为两个图表,但在一个图形中,这样当我保存图形时,我会看到两个图。目前,运行第二个情节会覆盖内存中的第一个情节,因此我只能保存第二个情节。

如何将它们绘制在一起?

我的代码如下。

plot1 = plt.figure()
fig,ax1 = plt.subplots()
ax1.plot(dfSat['time'],dfSat['wind_at_altitude'], 'b-', label = "speed", linewidth = 5.0)
plt.title('Wind Speeds - Saturday - {}'.format(windloc))
plt.xlabel('Time of day')
plt.ylabel('Wind speed (mph)')
ax1.plot(dfSat['time'],dfSat['gust_at_altitude'], 'r-', label = "gust", linewidth = 5.0)
plt.legend(loc="upper right")
ax1.text(0.05, 0.95, calcmeassat, transform=ax1.transAxes, fontsize=30,
        verticalalignment='top')
plt.ylim((0,100))

plot2 = plt.figure()
fig,ax2 = plt.subplots()
ax2.plot(dfSun['time'],dfSun['wind_at_altitude'], 'b-', label = "speed", linewidth = 5.0)
plt.title('Wind Speeds - Sunday - {}'.format(windloc))
plt.xlabel('Time of day')
plt.ylabel('Wind speed (mph)')
ax2.plot(dfSun['time'],dfSun['gust_at_altitude'], 'r-', label = "gust", linewidth = 5.0)
plt.legend(loc="upper right")
ax2.text(0.05, 0.95, calcmeassun, transform=ax2.transAxes, fontsize=30,
        verticalalignment='top')
plt.ylim((0,100))

不是这样的。子图就是它们的名称; plots inside a main plot.

这意味着如果你需要两个子图;那么你需要一个包含两个子图的图。

# figure object NOT plot object
# useful when you want only one plot NO subplots
fig = plt.figure() 

# 2 subplots inside 1 plot
# 1 row, 2 columns
fig, [ax1, ax2] = plt.subplots(1, 2)

# then call plotting method on each axis object to
# create plot on that subplot
sns.histplot(...., ax=ax1)
sns.violinplot(..., ax=ax2)

# or using matplotlib like this
ax1.plot()
ax2.plot()

详细了解 subplots

  • 如前所述,在您的情况下,您只需要一层子图,例如 nrows=1, ncols=2
  • 但是, 在 matplotlib 3.4+ 中有一个称为 subfigures, 的“子图子图”这样的东西使得更容易实现嵌套布局,例如:
    • How to create row titles for subplots
    • How to share colorbars within some subplots

支线

对于更简单的用例,创建 1x2 子图,左侧为 ax1,右侧为 ax2

# create 1x2 subplots
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(16, 4))

# plot saturdays on the left
dfSat.plot(ax=ax1, x='date', y='temp_min')
dfSat.plot(ax=ax1, x='date', y='temp_max')
ax1.set_ylim(-20, 50)
ax1.set_title('Saturdays')

# plot sundays on the right
dfSun.plot(ax=ax2, x='date', y='temp_min')
dfSun.plot(ax=ax2, x='date', y='temp_max')
ax2.set_ylim(-20, 50)
ax2.set_title('Sundays')

子图

假设您想要一些更复杂的东西,例如让左侧显示 2012 年和右侧显示 2015 年 suptitle

创建 1x2 子图(左侧 subfig_l 和右侧 subfig_r),左侧为 2x1 子图(顶部 ax_lt 底部 ax_lb),右侧为 2x1 子图(顶部 ax_rt 和底部 ax_rb):

# create 1x2 subfigures
fig = plt.figure(constrained_layout=True, figsize=(12, 5))
(subfig_l, subfig_r) = fig.subfigures(nrows=1, ncols=2, wspace=0.07)

# create top/box axes in left subfig
(ax_lt, ax_lb) = subfig_l.subplots(nrows=2, ncols=1)

# plot 2012 saturdays on left-top axes
dfSat12 = dfSat.loc[dfSat['date'].dt.year.eq(2012)]
dfSat12.plot(ax=ax_lt, x='date', y='temp_min')
dfSat12.plot(ax=ax_lt, x='date', y='temp_max')
ax_lt.set_ylim(-20, 50)
ax_lt.set_ylabel('Saturdays')

# plot 2012 sundays on left-top axes
dfSun12 = dfSun.loc[dfSun['date'].dt.year.eq(2012)]
dfSun12.plot(ax=ax_lb, x='date', y='temp_min')
dfSun12.plot(ax=ax_lb, x='date', y='temp_max')
ax_lb.set_ylim(-20, 50)
ax_lb.set_ylabel('Sundays')

# set suptitle for left subfig
subfig_l.suptitle('2012', size='x-large', weight='bold')

# create top/box axes in right subfig
(ax_rt, ax_rb) = subfig_r.subplots(nrows=2, ncols=1)

# plot 2015 saturdays on left-top axes
dfSat15 = dfSat.loc[dfSat['date'].dt.year.eq(2015)]
dfSat15.plot(ax=ax_rt, x='date', y='temp_min')
dfSat15.plot(ax=ax_rt, x='date', y='temp_max')
ax_rt.set_ylim(-20, 50)
ax_rt.set_ylabel('Saturdays')

# plot 2015 sundays on left-top axes
dfSun15 = dfSun.loc[dfSun['date'].dt.year.eq(2015)]
dfSun15.plot(ax=ax_rb, x='date', y='temp_min')
dfSun15.plot(ax=ax_rb, x='date', y='temp_max')
ax_rb.set_ylim(-20, 50)
ax_rb.set_ylabel('Sundays')

# set suptitle for right subfig
subfig_r.suptitle('2015', size='x-large', weight='bold')

供参考的示例数据:

import pandas as pd
from vega_datasets import data

df = data.seattle_weather()
df['date'] = pd.to_datetime(df['date'])
dfSat = df.loc[df['date'].dt.weekday.eq(5)]
dfSun = df.loc[df['date'].dt.weekday.eq(6)]