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

7
我正在绘制两个子图,它们共享相同的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会在两个子图上显示,但第一个图的格式不正确。我希望使用指定的参数在所有子图上显示x轴格式化。我还希望有独特的y标签。 - MBasith
4个回答

12

正如其他答案所提到的,要在两个子图上显示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)

输入图像描述


{btsdaf} - DavidG
4
你基本上是在撤销 matplotlib 在设置 sharex 时在幕后所做的工作,因为它会将除底部子图外的所有子图的 labelbottom 设为 False - tmdavison
labelbottom=True 对我不起作用。 - chill appreciator

3
有几件事情可以做。要么移除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()

这将产生:

在此输入图片描述


{btsdaf} - MBasith
1
它在Matplotlib 3.3.2中不再起作用。 - Serge Mosin

1
关于第一个问题,我建议不要添加额外的墨水来混淆情节。
现在,关于y轴标签。你必须使用从plt.subplots得到的坐标轴,将plt.ylabel('Pop')替换为axes[0].set_ylabel('Pop')plt.ylabel('Pop')替换为axes[1].set_ylabel('Temp')

0
fig,axes = plt.subplots(nrows = 2,ncols = 1,sharex = True)中删除sharex = True以获得单独的x轴。
对于y轴标签:
axes[0].set_ylabel('Pop')
axes[1].set_ylabel('Temp')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接