【问题标题】:How can I get axis of different length but same scale for subplots in matplotlib?如何在 matplotlib 中为子图获得不同长度但比例相同的轴?
【发布时间】:2016-08-25 04:39:05
【问题描述】:

例如,如果我有这 3 个要绘制的数据集:

a = np.arange(0,10,1)
b = np.arange(2,6,1)
c = np.arange(5,10,1)

显然,我不希望它们共享同一个轴,因为它们中的一些基本上只会有一个大的空图,在角落的某个地方有几个数据点。因此,理想情况下,我会拥有不同大小的子图,但都具有相同的比例(即步骤 1 在所有子图上具有相同的长度)。我知道我可以通过设置图形的大小来手动执行此操作,但是对于大量数据集或不太好的数字,这将是一个真正的痛苦。但是通过其他问题或文档搜索,我找不到任何可以设置轴上刻度线或其他东西的固定距离的东西。请注意,我不是在询问纵横比。纵横比可以不同,我只需要轴上的相同比例。 (见下图,希望能说明我的问题。注意:不,我的实际绘图中不需要比例尺,这是为了让你看看比例是如何相同的。) 谢谢。

【问题讨论】:

标签: python matplotlib


【解决方案1】:

经过大量研究,看起来确实没有任何简单的命令可以做到这一点。但首先,考虑到每个子图的 x 和 y 值的范围及其比率以及布局,GridSpec 将完成这项工作。

因此,对于我们的示例,布局如问题中所示,即最大的图片在顶部,两个较小的图片在下方彼此相邻。为了更容易,它们的 y 范围是相同的(但如果不是,我们将使用与 x 相同的计算)。现在,知道了这个布局,我们可以创建一个网格。垂直跨度为 20(因为我们有两行 4 个图,y 范围为 10),我们可能希望它们之间有一些空间用于轴标签、图例等,所以我们将添加额外的 5。第一个图有 x 范围10个,但是第二个和第三个数字的范围是4和5,一共是9个,我们可能还想要它们之间的空间,所以让我们多加3个。所以水平网格将跨越 12 个。因此,我们创建了一个 25 x 12 的网格,并将我们的地块放入该网格中,如下所示:

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

## GRIDSPEC INTRO - creating a grid to distribute the subplots with same scales and different sizes.
fig = plt.figure()
gs=gridspec.GridSpec(25,12)
## SUBPLOTS of GRIDSPEC
#the first (big) plot
axes1 = plt.subplot(gs[:10,:10])
ax1 = plt.plot(x,y) # plot some data here
ax1 = plt.xlim(1,10)
ax1 = plt.ylim(1,10)
# the second plot below the big one on the left
axes2 = plt.subplot(gs[15:,:4])
ax2 = plt.plot(x,y) # plot some data here
ax2 = plt.xlim(2,6)
ax2 = plt.ylim(1,10)
# the third plot - below the big one on the right
axes3 = plt.subplot(gs[15:,7:])
ax3 = plt.plot(x,y) # plot some data here
ax3 = plt.xlim(5,10)
ax3 = plt.ylim(1,10)
plt.show()

【讨论】:

    【解决方案2】:

    一个小时后:

    __author__ = 'madevelasco'
    
    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    
    
    def group(x, max, min, iters):
        total_range = max - min
        for i in range(0, iters):
            if (x > min + i*total_range/iters and x <= min + (i+1)*total_range/iters):
                return i
    
    
    
    def newPlots():
        df = pd.DataFrame(np.random.randn(100, 2), columns=['x', 'y'])
        df.plot(x = 'x', y = 'y', kind = 'scatter', alpha=0.5)
        plt.show()
    
        ##Sort by the column you want
        df.sort_values(['x'], ascending=[False], inplace=True)
        result = df.reset_index(drop=True).copy()
    
        #Number of groups you want
        iterations = 3
        max_range = df['x'].max()
        min_range = df['x'].min()
        total_range = max_range - min_range
    
        result['group'] = result.apply(lambda x: group(x['x'], max_range, min_range, iterations ), axis=1)
        print(result)
    
        for x in range (0, iterations):
    
            lower = min_range + (x)*total_range/iterations
            upper = min_range + (1+x)*total_range/iterations
            new = result[result['group'] == x]
            new.plot(x = 'x', y = 'y', kind = 'scatter', alpha=0.3)
            axes = plt.gca()
            axes.set_xlim([lower, upper])
            axes.set_ylim([df['y'].min(),df['y'].max()])
            plt.show()
    
    if __name__ == '__main__':
        newPlots()
    

    我用熊猫来做到这一点。老实说,可视化的想法是将所有数据放在一个图表中,但不会像那样分开。为了保持日期的概念,甚至为了可读性,应该固定其中一个轴。我在两次编辑之间做了

    所有点的图像

    子地块

    【讨论】:

    • 这些轴的长度相同并且共享相同的 x 轴,但我的轴不共享任何东西并且长度不同。我只希望单位在所有轴上都相同。所以基本上在这个比例1-10上,我希望“1”长1厘米,因此“a”的轴长10厘米,“b”的轴长4厘米,“c”的轴“长5厘米。 (请参阅更新的问题。)谢谢
    • 仍然不是我想要的。请参阅我更新的问题中的图像。 (xlim 和 ylim 对于每个子图都是不同的。所以显然我可以更改每个子图的限制,但是当我这样做时,每个图的规模都是不同的。这就是我正在努力解决的问题。)
    • 我认为子图的图像没有正确加载。只有一个情节的图像。仅从代码中,我看不出分组有何帮助。感谢您的努力,但如果没有一个简单的命令来完成,那么这个过于复杂的过程是不值得的。
    • 我修复了图像。该小组将其保留在均匀范围的零件上,而不是均匀的尺寸上。每个小组将评估信息将出现在哪个子图上
    • 哦,我明白你的意思了!不,抱歉,我不想根据范围对数据进行排序。我知道我在每个子图上想要什么,而 RANGE 是无关紧要的。唯一相关的是如何在同一 SCALE 的轴上制作刻度的 STEP。您的示例无济于事,因为每个图的步长为 0.2,范围为 1.6。所以很明显它们都是一样的。请使用我的示例数据来重现我的问题,而不是创建显示您想要的结果的问题。
    猜你喜欢
    • 1970-01-01
    • 2018-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-15
    • 2016-04-14
    • 2019-05-10
    • 2021-04-18
    相关资源
    最近更新 更多