在matplotlib

时间:2015-06-27 01:26:59

标签: python matplotlib

我的目标是在同一个窗口中创建三个子图。这些子图应该在一列中对齐,每一列在另一列之下。第一个子图不应该使用滑块小部件,其他两个应该,所以如果我将移动滑块,那么两个底部子图应该滚动。我最终得到了两个代码。我已经修改了一些代码来回答我的another question。棘手的部分是绘制部分,主要是作为试验和错误创建的:

#!/usr/bin/python

import numpy as np
import matplotlib.pyplot  as plt
from   matplotlib.widgets import Slider

fig, ax = plt.subplots(nrows=2, ncols=1, sharex=True, sharey=False)

# 1. On which (sub)plots this option is apply to 
#    (already existed or also for subplots created in future)? 
plt.subplots_adjust(bottom=0.25)

x_time = np.arange(0.0, 100.0, 0.1)
sin_s  = np.sin(x_time)
cos_s  = np.cos(x_time)
oscil  = np.cos(2 * np.pi * x_time) * np.exp(-x_time)

sin_l, = plt.plot(x_time, sin_s, "bo-", label="sin")
cos_l, = plt.plot(x_time, cos_s, "r.-", label="cos")

# 2. On which plots this option is apply to 
#    (already existed or also for subplots created in future)? 
plt.axis([0, 10, -1, 1])

####################################
# HERE COMES THE TRICKY PART WITH  #
# TWO ALTERNATIVES - THE RESULT OF #
# TRIAL AND ERROR. PLEASE SEE CODE #
# SNIPPETS BELLOW                  #
####################################


axcolor = 'lightgoldenrodyellow'
axpos = plt.axes([0.2, 0.1, 0.65, 0.03], axisbg=axcolor)
spos = Slider(axpos, 'Pos', 0.1, 90.0)

def update(val):
    pos = spos.val


    # 3. No matter which index is chosen (0 or 1), 
    #    it behaves exactly the same in both alternatives. 
    #    How is this possible?
    ax[0].axis([pos,pos+10,-1,1])
    # ax[1].axis([pos,pos+10,-1,1])
    fig.canvas.draw_idle()

spos.on_changed(update)

plt.show()

以下是我用于绘图的两个不同代码部分,这是我不理解的代码的试错部分:

# 1st alternative - this plot is scrollable:
ax[0].plot(x_time, oscil, "k-", label="oscilation")
ax[0].legend()


# 2nd alternative - this plot is not scrollable:
plt.subplot(211)
plt.plot(x_time, oscil, "k-", label="oscilation")
plt.title('A tale of 2 subplots')
plt.ylabel('Damped oscillation')

我试图将这些示例合并到我的最终解决方案中(有三个图可以从中滚动)。所以我在下一行中将nrows=2更改为nrows=3

fig, ax = plt.subplots(nrows=2, ncols=1, sharex=True, sharey=False)

但是如果我使用第一种替代方案,那么所有三个子图都是可滚动的,而不是两个。如果我使用第二种替代方案,那么我只得到两个子图,而不是三个,其中一个是可滚动的而另一个不是。

您能否回答以下问题:

  1. 评论:plt.subplots_adjust(bottom=0.25)
  2. 评论:plt.axis([0, 10, -1, 1])
  3. 评论:ax[0].axis([pos,pos+10,-1,1]) vs ax[1].axis([pos,pos+10,-1,1])
  4. 最重要的是:如何让它适用于三个子图?
  5. 最后是第一和第二替代方案之间的区别?
  6. 编辑,工作版本:

    #!/usr/bin/python
    
    import numpy as np
    import matplotlib.pyplot  as plt
    from   matplotlib.widgets import Slider
    
    plt.close('all')
    
    fig, ax = plt.subplots(nrows=3, ncols=1)
    plt.subplots_adjust(bottom=0.25)
    
    ########################################
    x_time = np.arange(0.0, 100.0, 0.1)
    
    oscil  = np.cos(2 * np.pi * x_time) * np.exp(-x_time)
    
    sin_s  = 2*np.sin(x_time)
    cos_s  = np.cos(x_time)
    ########################################
    ax[0].plot(x_time, oscil, "k-", label="oscilation")
    ax[1].plot(x_time, sin_s, "bo-", label="sin")
    ax[2].plot(x_time, cos_s, "r.-", label="cos")
    ########################################
    ax[0].set_xlim([0, 10])
    ax[1].set_ylim([-2, 2])
    ax[2].set_ylim([-1, 1])
    ########################################
    axcolor = 'lightgoldenrodyellow'
    axpos = plt.axes([0.2, 0.1, 0.65, 0.03], axisbg=axcolor)
    spos = Slider(axpos, 'Pos', 0.1, 90.0)
    
    def update(val):
        pos = spos.val
    
        ax[1].axis([pos,pos+10,-2,2])
        ax[2].axis([pos,pos+10,-1,1])
        fig.canvas.draw_idle()
    
    spos.on_changed(update)
    
    plt.show()
    

1 个答案:

答案 0 :(得分:1)

您的问题都可以通过matplotlib.figure API documentationmatplotlib.pyplot API documentation来解答。

  

1。此选项适用于哪些(子)图(已存在或未来创建的子图)?

     

plt.subplots_adjust(bottom=0.25)

所有可能的参数是:

subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)

这些都更新了子图参数which are all documented here

  

所有尺寸均为图宽度或高度底部的一小部分:   图的子图的底部。

因此,调用plt.subplots_adjust(bottom=0.25)会使整个图的下边距(包含两个子图的区域) 25%的图形高度。

在此示例中,这是防止滑块与图形的其余部分发生碰撞所必需的。注释掉那条线,看看我的意思。

  

2. :此选项适用于哪些绘图(已存在或将来创建的子图)?

     

plt.axis([0, 10, -1, 1])

这将以[xmin, xmax, ymin, ymax]的形式设置绘图的轴限制。 See this portion of the documentation

你设置plt对象的轴有点奇怪 - 但是,这样做只在最后一个子图上设置了一次轴。

  

3. 无论选择哪个索引(0或1),它在两个备选方案中的行为都完全相同。这怎么可能?      ax[0].axis([pos,pos+10,-1,1])

     

ax[1].axis([pos,pos+10,-1,1])

您使用kwargs sharex=Truesharey=False创建了子图。由于最初创建的轴的ymin为-1且ymax为1,因此在任何一种情况下调用update都不会更改轴。

由于您初始化了xminxmax(请参阅 2。),因此您在任何情况下都只更新了ymin=-1ymax=1。在这种情况下,更新哪个轴无关紧要,因为sharex行为将为两个轴更新此值。

但是,尝试更新y min和max - 更新轴属性在这种情况下将不相同。

  

4。最重要的是:如何让它适用于三个子图?

     

5. 最后是第一和第二替代方案之间的区别?

我不清楚你想在这做什么,所以我先从 5。开始。

# 1st alternative - this plot is scrollable:
ax[0].plot(x_time, oscil, "k-", label="oscilation")
ax[0].legend()

这会将您的振荡绘制到您调用plt.subplots时创建的第一个子图中,因为您在ax[0]上调用了绘图。调用ax[0].legend()会根据您提供的标签和笔划绘制图例。

# 2nd alternative - this plot is not scrollable:
plt.subplot(211)
plt.plot(x_time, oscil, "k-", label="oscilation")
plt.title('A tale of 2 subplots')
plt.ylabel('Damped oscillation')

这会在第一个位置创建一个 new 子图 - 请参阅子图文档。它不会与您之前创建的图表共享轴。

我会把#4留给你,但如果你有任何具体问题,请告诉我。