合并具有共享x轴的子图

33
我有两个图表,它们的x轴相同,但y轴的刻度不同。
常规坐标轴的图表显示了一条衰减趋势的数据,并使用y半对数刻度来表示拟合的准确性。
fig1 = plt.figure(figsize=(15,6))
ax1 = fig1.add_subplot(111)

# Plot of the decay model 
ax1.plot(FreqTime1,DecayCount1, '.', color='mediumaquamarine')

# Plot of the optimized fit
ax1.plot(x1, y1M, '-k', label='Fitting Function: $f(t) = %.3f e^{%.3f\t} \
         %+.3f$' % (aR1,kR1,bR1))

ax1.set_xlabel('Time (sec)')
ax1.set_ylabel('Count')
ax1.set_title('Run 1 of Cesium-137 Decay')

# Allows me to change scales
# ax1.set_yscale('log')
ax1.legend(bbox_to_anchor=(1.0, 1.0), prop={'size':15}, fancybox=True, shadow=True)

enter image description here enter image description here

现在,我正在努力弄清楚如何将它们紧密地实现在一起,就像这个链接提供的示例一样http://matplotlib.org/examples/pylab_examples/subplots_demo.html
特别是这个。

enter image description here

当看到这个例子的代码时,我对如何实现以下三个事情感到有些困惑:
1)以不同的比例缩放坐标轴
2)保持指数衰减图的图形大小不变,但使线图的y轴大小较小,x轴大小相同。
例如:

enter image description here

3)只让函数的标签出现在衰减图中。
非常感谢任何帮助。
3个回答

51

看看代码和它的注释:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import gridspec

# Simple data to display in various forms
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)

fig = plt.figure()
# set height ratios for subplots
gs = gridspec.GridSpec(2, 1, height_ratios=[2, 1]) 

# the first subplot
ax0 = plt.subplot(gs[0])
# log scale for axis Y of the first subplot
ax0.set_yscale("log")
line0, = ax0.plot(x, y, color='r')

# the second subplot
# shared axis X
ax1 = plt.subplot(gs[1], sharex = ax0)
line1, = ax1.plot(x, y, color='b', linestyle='--')
plt.setp(ax0.get_xticklabels(), visible=False)
# remove last tick label for the second subplot
yticks = ax1.yaxis.get_major_ticks()
yticks[-1].label1.set_visible(False)

# put legend on first subplot
ax0.legend((line0, line1), ('red line', 'blue line'), loc='lower left')

# remove vertical gap between subplots
plt.subplots_adjust(hspace=.0)
plt.show()

这里输入图片描述


@Serenity 很棒的答案!但是如果我使用“fig,axis = plt.subplots(nrows = 4)”来创建我的坐标轴数组,是否有可能拥有共享x轴? - Yushan ZHANG
当然可以,为什么不呢? - Serenity
@Serenity 嗯,如果使用 plt.plot(),我可以指定 sharex,那么这是可能的。但在 Pandas 中,我无法接触到底层的 sharex,我必须创建一个新的轴来传递给 DataFrame.plot()。这就是为什么我喜欢你的答案! - Yushan ZHANG
3
请注意,可以在一个函数调用中创建两个坐标轴:fig, (ax0, ax1) = plt.subplots(2,1, sharex=True, gridspec_kw=dict(height_ratios=[2, 1]))。在此调用中,参数2,1表示将创建两个行和一个列的子图网格,sharex=True表示共享x轴刻度线,dict(height_ratios=[2,1])是用于指定子图高度比例的字典参数。 - normanius

13

这是我的解决方案:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)

fig, (ax1,ax2) = plt.subplots(nrows=2, sharex=True, subplot_kw=dict(frameon=False)) # frameon=False removes frames

plt.subplots_adjust(hspace=.0)
ax1.grid()
ax2.grid()

ax1.plot(x, y, color='r')
ax2.plot(x, y, color='b', linestyle='--')

在此输入图像描述

还有一个选项是seaborn.FacetGrid,但这需要Seaborn和Pandas库。


1
下面是一些适应性调整,以展示如何在绘制pandas数据帧时添加一个组合图例。 可以使用ax = ax0在给定的ax上进行绘制,ax0.get_legend_handles_labels()获取图例的信息。
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

dates = pd.date_range('20210101', periods=100, freq='D')
df0 = pd.DataFrame({'x': np.random.normal(0.1, 1, 100).cumsum(),
                    'y': np.random.normal(0.3, 1, 100).cumsum()}, index=dates)
df1 = pd.DataFrame({'z': np.random.normal(0.2, 1, 100).cumsum()}, index=dates)

fig, (ax0, ax1) = plt.subplots(nrows=2, sharex=True, gridspec_kw={'height_ratios': [2, 1], 'hspace': 0})

df0.plot(ax=ax0, color=['dodgerblue', 'crimson'], legend=False)
df1.plot(ax=ax1, color='limegreen', legend=False)

# put legend on first subplot
handles0, labels0 = ax0.get_legend_handles_labels()
handles1, labels1 = ax1.get_legend_handles_labels()
ax0.legend(handles=handles0 + handles1, labels=labels0 + labels1)

# remove last tick label for the second subplot
yticks = ax1.get_yticklabels()
yticks[-1].set_visible(False)

plt.tight_layout()
plt.show()

using pandas plotting


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