【问题标题】:two (or more) graphs in one plot with different x-axis AND y-axis scales in pythonpython中具有不同x轴和y轴刻度的一个图中的两个(或多个)图
【发布时间】:2017-08-01 17:26:04
【问题描述】:

我想要一个轴对象上的 3 个图形,例如:

#example x- and y-data
x_values1=[1,2,3,4,5]
y_values1=[1,2,3,4,5]

x_values2=[-1000,-800,-600,-400,-200]
y_values2=[10,20,39,40,50]

x_values3=[150,200,250,300,350]
y_values3=[10,20,30,40,50]


#make axes
fig=plt.figure()
ax=fig.add_subplot(111)

现在我想将所有三个数据集添加到 ax。但是它们不应该共享任何 x 轴或 y 轴(从那时起,由于比例不同,一个会比另一个小得多。我需要 ax.twinx()、ax.twiny 之类的东西(),但 x 轴和 y 轴都需要独立。

我想这样做,因为我想将两个附加的图(第三个,类似于第二个)放在一个图中(“将它们放在彼此之上”)。 Plot1 Plot2

然后我会将第二个图的 x/y 标签(和/或刻度、限制)放在右侧/顶部,并将另一个图的 x/y 限制放在底部/左侧。我不需要 3. 情节的 x/y 标签。

我该怎么做?

【问题讨论】:

标签: python matplotlib plot


【解决方案1】:

我们的想法是在同一位置创建三个子图。为了确保它们被识别为不同的地块,它们的属性需要有所不同——实现这一点的最简单方法就是提供不同的标签,ax=fig.add_subplot(111, label="1")

剩下的就是简单地调整所有的坐标轴参数,这样结果图看起来就很吸引人了。 设置所有参数有点工作,但以下应该可以满足您的需求。

import matplotlib.pyplot as plt

x_values1=[1,2,3,4,5]
y_values1=[1,2,2,4,1]

x_values2=[-1000,-800,-600,-400,-200]
y_values2=[10,20,39,40,50]

x_values3=[150,200,250,300,350]
y_values3=[10,20,30,40,50]


fig=plt.figure()
ax=fig.add_subplot(111, label="1")
ax2=fig.add_subplot(111, label="2", frame_on=False)
ax3=fig.add_subplot(111, label="3", frame_on=False)

ax.plot(x_values1, y_values1, color="C0")
ax.set_xlabel("x label 1", color="C0")
ax.set_ylabel("y label 1", color="C0")
ax.tick_params(axis='x', colors="C0")
ax.tick_params(axis='y', colors="C0")

ax2.scatter(x_values2, y_values2, color="C1")
ax2.xaxis.tick_top()
ax2.yaxis.tick_right()
ax2.set_xlabel('x label 2', color="C1") 
ax2.set_ylabel('y label 2', color="C1")       
ax2.xaxis.set_label_position('top') 
ax2.yaxis.set_label_position('right') 
ax2.tick_params(axis='x', colors="C1")
ax2.tick_params(axis='y', colors="C1")

ax3.plot(x_values3, y_values3, color="C3")
ax3.set_xticks([])
ax3.set_yticks([])

plt.show()

【讨论】:

  • 优秀!!这正是我需要的答案!我不知道(或想过)我可以在同一位置有多个子图...谢谢!
  • 是的,一个常见的陷阱是多次创建完全相同的子图,如上所述,可以通过传递不同的参数来防止这种情况。因此,如果这回答了问题,请考虑accepting the answer,这样它就不会一直悬而未决。
【解决方案2】:

您还可以标准化数据,使其共享相同的限制,然后“手动”绘制所需的第二个比例的限制。 此函数将数据标准化到第一组点的范围内:

def standardize(data):
    for a in range(2):
        span = max(data[0][a]) - min(data[0][a])
        min_ = min(data[0][a])
        for idx in range(len(data)):
            standardize = (max(data[idx][a]) - min(data[idx][a]))/span
            data[idx][a] = [i/standardize + min_ - min([i/standardize 
                            for i in data[idx][a]]) for i in data[idx][a]]
    return data

然后,绘制数据很容易:

import matplotlib.pyplot as plt
data = [[[1,2,3,4,5],[1,2,2,4,1]], [[-1000,-800,-600,-400,-200], [10,20,39,40,50]], [[150,200,250,300,350], [10,20,30,40,50]]]
limits = [(min(data[1][a]), max(data[1][a])) for a in range(2)]

norm_data = standardize(data)

fig, ax = plt.subplots()

for x, y in norm_data:
    ax.plot(x, y)

ax2, ax3 = ax.twinx(), ax.twiny()
ax2.set_ylim(limits[1])
ax3.set_xlim(limits[0])

plt.show()

由于所有数据点都有第一组点的限制,我们可以将它们绘制在同一轴上。然后,使用所需的第二个 x 和 y 轴的限制,我们可以设置这两个轴的限制。

【讨论】:

    【解决方案3】:

    在此示例中,您可以在每个 x-y 轴上绘制多条线,并在每条线中绘制legend

    import numpy as np
    import matplotlib.pyplot as plt
    X1 = np.arange(10)
    X1 = np.stack([X1, X1])
    Y1 = np.random.randint(1, 10, (2, 10))
    X2 = np.arange(0, 1000, 200)
    X2 = np.stack([X2, X2])
    Y2 = np.random.randint(100, 200, (2, 5))
    
    
    x_label_names = ['XXX', 'xxx']
    y_label_names = ['YYY', 'yyy']
    X1_legend_names = ['X1_legend1', 'X1_legend2']
    X2_legend_names = ['X2_legend1', 'X2_legend2']
    
    
    def plot_by_two_xaxis(X1, Y1, X2, Y2, x_label_names: list, y_label_names: list, X1_legend_names: list, X2_legend_names: list):
        fig = plt.figure()
        ax1s = []
        ax2s = []
        lines = []
        j = 0
        for i in range(len(X1)):
            j += 1
            ax1s.append(fig.add_subplot(111, label=f"{j}", frame_on=(j == 1)))
        for i in range(len(X2)):
            j += 1
            ax2s.append(fig.add_subplot(111, label=f"{j}", frame_on=(j == 1)))
    
        k = 0
        for i in range(len(X1)):
            lines.append(ax1s[i].plot(X1[i], Y1[i], color=f"C{k}")[0])
            if i == 0:
                ax1s[i].set_xlabel(x_label_names[0], color=f"C{k}")
                ax1s[i].set_ylabel(y_label_names[0], color=f"C{k}")
                ax1s[i].tick_params(axis='x', colors=f"C{k}")
                ax1s[i].tick_params(axis='y', colors=f"C{k}")
            else:
                ax1s[i].set_xticks([])
                ax1s[i].set_yticks([])
            k += 1
    
        for i in range(len(X1)):
            lines.append(ax2s[i].plot(X2[i], Y2[i], color=f"C{k}")[0])
            if i == 0:
                ax2s[i].xaxis.tick_top()
                ax2s[i].yaxis.tick_right()
                ax2s[i].set_xlabel(x_label_names[1], color=f"C{k}")
                ax2s[i].set_ylabel(y_label_names[1], color=f"C{k}")
                ax2s[i].xaxis.set_label_position('top')
                ax2s[i].yaxis.set_label_position('right')
                ax2s[i].tick_params(axis='x', colors=f"C{k}")
                ax2s[i].tick_params(axis='y', colors=f"C{k}")
            else:
                ax2s[i].set_xticks([])
                ax2s[i].set_yticks([])
            k += 1
    
        ax1s[0].legend(lines, X1_legend_names + X2_legend_names)
    
        plt.show()
    
    
    plot_by_two_xaxis(X1, Y1, X2, Y2, x_label_names,
                    y_label_names, X1_legend_names, X2_legend_names)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-18
      • 1970-01-01
      • 2017-12-02
      • 1970-01-01
      • 1970-01-01
      • 2013-01-22
      • 1970-01-01
      相关资源
      最近更新 更多