2014-12-30 74 views
2

是否可以在matplotlib軸中嵌入不斷變化的圖形數量?例如,inset_axes方法是用來放置父軸內插圖軸:使用matplotlib在另一個軸中嵌入多個插入軸

enter image description here

然而,我有重複的多個行和我想包括每一行的最後一個軸對象內的一些插入軸。

fig, ax = plt.subplots(2,4, figsize=(15,15)) 
for i in range(2): 
    ax[i][0].plot(np.random.random(40)) 
    ax[i][2].plot(np.random.random(40)) 
    ax[i][3].plot(np.random.random(40)) 

    # number of inset axes 
    number_inset = 5 
    for j in range(number_inset): 
     ax[i][4].plot(np.random.random(40)) 

enter image description here

這裏,而不是在最後一欄畫了5個情節,我想包含幾個情節插入軸。事情是這樣的:

enter image description here

這樣做的原因是,每一行指的是不同的項目進行策劃和最後一列應該包含這樣的部件。有沒有辦法在matplotlib中做到這一點,或者是另一種可視化的方式?

感謝

+3

你真的需要使用'inset_axes'?如何直接將小軸添加到圖中(例如['GridSpec'](http://matplotlib.org/users/gridspec.html))? – hitzg

+0

你說得對。謝謝! –

回答

2

正如@hitzg提到的,最常見的方式來完成這樣的事情是使用GridSpecGridSpec創建一個虛構的網格對象,您可以切片以生成子圖。這是一種簡單的方法來對齊相當複雜的佈局,您想要遵循常規網格。

但是,在這種情況下,如何使用它可能並不明顯。您需要創建一個GridSpec,numrows * numinsets行到numcols列,然後通過間隔numinsets對其進行切片來創建「主」軸。

在下面的例子(2行,4列,3個插圖),我們就通過gs[:3, 0]切片得到左上角的「主」軸,gs[3:, 0]得到左下「主」軸,gs[:3, 1]得到接下來的上軸等等。對於插圖,每一個都是gs[i, -1]

作爲一個完整的例子:

import numpy as np 
import matplotlib.pyplot as plt 

def build_axes_with_insets(numrows, numcols, numinsets, **kwargs): 
    """ 
    Makes a *numrows* x *numcols* grid of subplots with *numinsets* subplots 
    embedded as "sub-rows" in the last column of each row. 

    Returns a figure object and a *numrows* x *numcols* object ndarray where 
    all but the last column consists of axes objects, and the last column is a 
    *numinsets* length object ndarray of axes objects. 
    """ 
    fig = plt.figure(**kwargs) 
    gs = plt.GridSpec(numrows*numinsets, numcols) 

    axes = np.empty([numrows, numcols], dtype=object) 
    for i in range(numrows): 
     # Add "main" axes... 
     for j in range(numcols - 1): 
      axes[i, j] = fig.add_subplot(gs[i*numinsets:(i+1)*numinsets, j]) 

     # Add inset axes... 
     for k in range(numinsets): 
      m = k + i * numinsets 
      axes[i, -1][k] = fig.add_subplot(gs[m, -1]) 

    return fig, axes 

def plot(axes): 
    """Recursive plotting function just to put something on each axes.""" 
    for ax in axes.flat: 
     data = np.random.normal(0, 1, 100).cumsum() 
     try: 
      ax.plot(data) 
      ax.set(xticklabels=[], yticklabels=[]) 
     except AttributeError: 
      plot(ax) 

fig, axes = build_axes_with_insets(2, 4, 3, figsize=(12, 6)) 
plot(axes) 
fig.tight_layout() 
plt.show() 

enter image description here

+0

很好的回答。 GridSpec是我所需要的。 –

+0

我想知道您的解決方案是否可以適應我們事先不知道'numinsets'的情況。同時,我重新安排了'GridSpec'的輸出並使用'GridSpecFromSubplotSpec'。無論如何,我會發布它,看看是否有改進。 –

1

這是我做過什麼,以獲得相同的結果竟未事先插圖地塊的數量。

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

fig = plt.figure(figsize=(12,6)) 

nrows = 2 
ncols = 4 

# changing the shape of GridSpec's output 
outer_grid = gridspec.GridSpec(nrows, ncols) 
grid = [] 
for i in range(nrows*ncols): 
    grid.append(outer_grid[i]) 
outer_grid = np.array(grid).reshape(nrows,ncols) 

for i in range(nrows): 
    inner_grid_1 = gridspec.GridSpecFromSubplotSpec(1, 1, 
       subplot_spec=outer_grid[i][0]) 
    ax = plt.Subplot(fig, inner_grid_1[0]) 
    ax.plot(np.random.normal(0,1,50).cumsum()) 
    fig.add_subplot(ax) 

    inner_grid_2 = gridspec.GridSpecFromSubplotSpec(1, 1, 
       subplot_spec=outer_grid[i][1]) 
    ax2 = plt.Subplot(fig, inner_grid_2[0]) 
    ax2.plot(np.random.normal(0,1,50).cumsum()) 
    fig.add_subplot(ax2) 

    inner_grid_3 = gridspec.GridSpecFromSubplotSpec(1, 1, 
       subplot_spec=outer_grid[i][2]) 
    ax3 = plt.Subplot(fig, inner_grid_3[0]) 
    ax3.plot(np.random.normal(0,1,50).cumsum()) 
    fig.add_subplot(ax3) 

    # this value can be set based on some other calculation depending 
    # on each row 
    numinsets = 3 
    inner_grid_4 = gridspec.GridSpecFromSubplotSpec(numinsets, 1, 
       subplot_spec=outer_grid[i][3]) 

    # Adding subplots to the last inner grid 
    for j in range(inner_grid_4.get_geometry()[0]): 
     ax4 = plt.Subplot(fig, inner_grid_4[j]) 
     ax4.plot(np.random.normal(0,1,50).cumsum()) 
     fig.add_subplot(ax4) 

# Removing labels 
for ax in fig.axes: 
    ax.set(xticklabels=[], yticklabels=[]) 

fig.tight_layout() 

enter image description here

+0

我注意到一個小小的改進。如果我們移動'fig.add_subplot'(例如'ax4 = fig.add_subplot(inner_grid_4 [j]); ax4.plot(np.random.normal(0,1,50)),可以刪除'plt.Subplot'。 cumsum())') –