Matplotlib 在所有子图上显示 x 刻度和唯一的 y 标签

Matplotlib show x-ticks on all subplots and unique y label

我正在绘制共享相同 x 轴的两个子图,但是当我绘制时,我只看到第二个子图上的 x 轴刻度。如何让 x 刻度在两个子图中都可见?

我还想为两个子图设置 y 标签,但只有第二个是可见的。你能帮忙在两个子图上显示 y 标签吗?

下面是我的可重现代码。

#!/usr/bin/python3
import pandas as pd
desired_width = 1500
pd.set_option('display.width', desired_width)
import matplotlib.pyplot as plt
import numpy as np


df = pd.DataFrame([{'DATETIME': '2017-09-29 01:00,', 'Population': 1000, 'Temp': 90, 'State': 'California'},
                   {'DATETIME': '2017-09-29 01:00,', 'Population': 2000, 'Temp': 70, 'State': 'Illinois'},
                   {'DATETIME': '2017-09-29 01:00,', 'Population': 3000, 'Temp': 50, 'State': 'Georgia'},
                   {'DATETIME': '2017-09-29 02:00,', 'Population': 2000, 'Temp': 40, 'State': 'California'},
                   {'DATETIME': '2017-09-29 02:00,', 'Population': 6000, 'Temp': 20, 'State': 'Illinois'},
                   {'DATETIME': '2017-09-29 02:00,', 'Population': 4000, 'Temp': 30, 'State': 'Georgia'},
                   {'DATETIME': '2017-09-29 03:00,', 'Population': 3000, 'Temp': 40, 'State': 'California'},
                   {'DATETIME': '2017-09-29 03:00,', 'Population': 4000, 'Temp': 60, 'State': 'Illinois'},
                   {'DATETIME': '2017-09-29 03:00,', 'Population': 2000, 'Temp': 80, 'State': 'Georgia'}])

df.index = df['DATETIME']
df.index = (pd.to_datetime(df.index)).strftime("%m/%d %H:00")

fig, axes = plt.subplots(nrows=2, ncols=1, sharex=True)

df.groupby('State')['Population'].plot(kind='line', linestyle='--', alpha=0.5, marker='o', legend=True, ax=axes[0])
plt.ylabel('Pop')
df.groupby('State')['Temp'].plot(kind='line', linestyle='--', alpha=0.5, marker='o', legend=True, ax=axes[1])
plt.ylabel('Temp')
plt.tick_params(axis='both', which='both', labelsize=7)
plt.tight_layout()
plt.show()

当前图表输出:

您可以做几件事。要么删除 sharex = True。或者,如果您想使用它,sharex 将 x 刻度设置为不可见,即 set_visible(False)。因此,您可以将它们设置为 True 以停止此操作。

为了让子图的格式相同,您需要为每个子图设置刻度参数,方法是对两个子图使用 axes[0].tick_params(axis='both', which='both', labelsize=7)(即重复 axes[1]

请注意,我个人更喜欢使用面向对象的 matpotlib API,即使用 ax.set_ylabel() 而不是 plt.ylabel(),因为我认为它可以更好地控制您正在使用的子图和轴。因此,我也在这方面稍微修改了你的代码

df = pd.DataFrame([{'DATETIME': '2017-09-29 01:00,', 'Population': 1000, 'Temp': 90, 'State': 'California'},
                   {'DATETIME': '2017-09-29 01:00,', 'Population': 2000, 'Temp': 70, 'State': 'Illinois'},
                   {'DATETIME': '2017-09-29 01:00,', 'Population': 3000, 'Temp': 50, 'State': 'Georgia'},
                   {'DATETIME': '2017-09-29 02:00,', 'Population': 2000, 'Temp': 40, 'State': 'California'},
                   {'DATETIME': '2017-09-29 02:00,', 'Population': 6000, 'Temp': 20, 'State': 'Illinois'},
                   {'DATETIME': '2017-09-29 02:00,', 'Population': 4000, 'Temp': 30, 'State': 'Georgia'},
                   {'DATETIME': '2017-09-29 03:00,', 'Population': 3000, 'Temp': 40, 'State': 'California'},
                   {'DATETIME': '2017-09-29 03:00,', 'Population': 4000, 'Temp': 60, 'State': 'Illinois'},
                   {'DATETIME': '2017-09-29 03:00,', 'Population': 2000, 'Temp': 80, 'State': 'Georgia'}])

df.index = df['DATETIME']
df.index = (pd.to_datetime(df.index)).strftime("%m/%d %H:00")

fig, axes = plt.subplots(nrows=2, ncols=1, sharex=True)

df.groupby('State')['Population'].plot(kind='line', linestyle='--', alpha=0.5, marker='o', legend=True, ax=axes[0])
axes[0].set_ylabel('Pop')
df.groupby('State')['Temp'].plot(kind='line', linestyle='--', alpha=0.5, marker='o', legend=True, ax=axes[1])
axes[1].set_ylabel('Temp')

# Set the formatting the same for both subplots
axes[0].tick_params(axis='both', which='both', labelsize=7)
axes[1].tick_params(axis='both', which='both', labelsize=7)

# set ticks visible, if using sharex = True. Not needed otherwise
for tick in axes[0].get_xticklabels():
    tick.set_visible(True)

plt.tight_layout()
plt.show()

给出:

fig, axes = plt.subplots(nrows=2, ncols=1, sharex=True) 中删除 sharex=True 以具有单独的 x 轴。

对于 ylabels

axes[0].set_ylabel('Pop')
axes[1].set_ylabel('Temp')

关于第一个问题,我建议不要用额外的墨水来扰乱情节。

现在,进入 y 标签。你必须使用从 plt.subplots 获得的坐标轴替换

plt.ylabel('Pop') 来自 axes[0].set_ylabel('Pop')plt.ylabel('Pop') 来自 axes[1].set_ylabel('Temp')

正如其他答案所提到的,要让 ylabel 出现在两个子图中,您可以在此处使用面向对象的界面 axes[0].set_ylabelaxes[1].set_ylabel.

您还应该在两个轴上使用 .tick_params 以获得相同大小的刻度标签等。对于两个子图

最后,为了让刻度标签显示在第一个子图中,作为循环遍历所有刻度并将它们设置为可见的替代方法,您可以通过再提供一个来实现相同的目的选项 tick_params: labelbottom=True.

fig, axes = plt.subplots(nrows=2, ncols=1, sharex=True)

df.groupby('State')['Population'].plot(kind='line', linestyle='--', alpha=0.5, marker='o', legend=True, ax=axes[0])
axes[0].set_ylabel('Pop')
df.groupby('State')['Temp'].plot(kind='line', linestyle='--', alpha=0.5, marker='o', legend=True, ax=axes[1])
axes[1].set_ylabel('Temp')
axes[0].tick_params(axis='both', which='both', labelsize=7, labelbottom=True)
axes[1].tick_params(axis='both', which='both', labelsize=7)