2013-07-03 18 views
35

Se si desidera inserire una trama piccola all'interno di una più grande, è possibile utilizzare Axes, ad esempio here.Incorporamento di piccoli grafici all'interno di sottotrame in matplotlib

Il problema è che non so come fare lo stesso all'interno di una sottotrama.

Ho diverse sottotrame e vorrei tracciare una piccola trama all'interno di ogni sottotrama. Il codice di esempio potrebbe essere qualcosa di simile:

import numpy as np 
import matplotlib.pyplot as plt 

fig = plt.figure() 

for i in range(4): 
    ax = fig.add_subplot(2,2,i) 
    ax.plot(np.arange(11),np.arange(11),'b') 

    #b = ax.axes([0.7,0.7,0.2,0.2]) 
    #it gives an error, AxesSubplot is not callable 

    #b = plt.axes([0.7,0.7,0.2,0.2]) 
    #plt.plot(np.arange(3),np.arange(3)+11,'g') 
    #it plots the small plot in the selected position of the whole figure, not inside the subplot 

Tutte le idee?

Grazie in anticipo!

+0

Sede [questo post correlati] (http://stackoverflow.com/questions/14589600/matplotlib-insets-in-subplots) – wflynny

+0

Lavorando sulla soluzione, ho trovato un altro problema ... http://stackoverflow.com/questions/17478165/fig-add-subplot-transform-doesnt-work – Pablo

+0

Grazie mille ad entrambi. Potrei fare ciò che stavo cercando con zoomed_inset_axis da AxesGrid come suggerito da Bill, e anche con la funzione di Pablo. Infine sto usando la funzione di Pablo perché è più confortevole di AxesGrid per tracciare tutte le piccole figure con le stesse dimensioni in tutte le sottotrame. Grazie ancora! – Argitzen

risposta

42

Ho scritto una funzione molto simile a plt.axes. Potresti usarlo per tracciare i tuoi sottototteri secondari. V'è un esempio ...

import matplotlib.pyplot as plt 
import numpy as np 

def add_subplot_axes(ax,rect,axisbg='w'): 
    fig = plt.gcf() 
    box = ax.get_position() 
    width = box.width 
    height = box.height 
    inax_position = ax.transAxes.transform(rect[0:2]) 
    transFigure = fig.transFigure.inverted() 
    infig_position = transFigure.transform(inax_position)  
    x = infig_position[0] 
    y = infig_position[1] 
    width *= rect[2] 
    height *= rect[3] # <= Typo was here 
    subax = fig.add_axes([x,y,width,height],axisbg=axisbg) 
    x_labelsize = subax.get_xticklabels()[0].get_size() 
    y_labelsize = subax.get_yticklabels()[0].get_size() 
    x_labelsize *= rect[2]**0.5 
    y_labelsize *= rect[3]**0.5 
    subax.xaxis.set_tick_params(labelsize=x_labelsize) 
    subax.yaxis.set_tick_params(labelsize=y_labelsize) 
    return subax 

def example1(): 
    fig = plt.figure(figsize=(10,10)) 
    ax = fig.add_subplot(111) 
    rect = [0.2,0.2,0.7,0.7] 
    ax1 = add_subplot_axes(ax,rect) 
    ax2 = add_subplot_axes(ax1,rect) 
    ax3 = add_subplot_axes(ax2,rect) 
    plt.show() 

def example2(): 
    fig = plt.figure(figsize=(10,10)) 
    axes = [] 
    subpos = [0.2,0.6,0.3,0.3] 
    x = np.linspace(-np.pi,np.pi) 
    for i in range(4): 
     axes.append(fig.add_subplot(2,2,i)) 
    for axis in axes: 
     axis.set_xlim(-np.pi,np.pi) 
     axis.set_ylim(-1,3) 
     axis.plot(x,np.sin(x)) 
     subax1 = add_subplot_axes(axis,subpos) 
     subax2 = add_subplot_axes(subax1,subpos) 
     subax1.plot(x,np.sin(x)) 
     subax2.plot(x,np.sin(x)) 
if __name__ == '__main__': 
    example2() 
    plt.show() 

enter image description here

+0

Grazie! E 'stato molto utile! – Argitzen

+0

Grazie per questo! – TheBigH

+0

Sapresti come rendere semitrasparente la trama secondaria? – jojo

23

È ora possibile fare questo con matplotlibs inset_axes metodo (vedi docs):

from mpl_toolkits.axes_grid.inset_locator import inset_axes 
inset_axes = inset_axes(parent_axes, 
        width="30%", # width = 30% of parent_bbox 
        height=1., # height : 1 inch 
        loc=3) 

Aggiornamento: ComeKuti punte out, per matplotlib versione 2.1 o successiva, è necessario modificare l'istruzione import su:

from mpl_toolkits.axes_grid1.inset_locator import inset_axes 
7

enter image description here

from mpl_toolkits.axes_grid.inset_locator import inset_axes 
import matplotlib.pyplot as plt 
import numpy as np 

# create some data to use for the plot 
dt = 0.001 
t = np.arange(0.0, 10.0, dt) 
r = np.exp(-t[:1000]/0.05)    # impulse response 
x = np.random.randn(len(t)) 
s = np.convolve(x, r)[:len(x)]*dt # colored noise 

fig = plt.figure(figsize=(9, 4),facecolor='white') 
ax = fig.add_subplot(121) 
# the main axes is subplot(111) by default 
plt.plot(t, s) 
plt.axis([0, 1, 1.1*np.amin(s), 2*np.amax(s)]) 
plt.xlabel('time (s)') 
plt.ylabel('current (nA)') 
plt.title('Subplot 1: \n Gaussian colored noise') 

# this is an inset axes over the main axes 
inset_axes = inset_axes(ax, 
        width="50%", # width = 30% of parent_bbox 
        height=1.0, # height : 1 inch 
        loc=1) 
n, bins, patches = plt.hist(s, 400, normed=1) 
#plt.title('Probability') 
plt.xticks([]) 
plt.yticks([]) 

ax = fig.add_subplot(122) 
# the main axes is subplot(111) by default 
plt.plot(t, s) 
plt.axis([0, 1, 1.1*np.amin(s), 2*np.amax(s)]) 
plt.xlabel('time (s)') 
plt.ylabel('current (nA)') 
plt.title('Subplot 2: \n Gaussian colored noise') 

plt.tight_layout() 
plt.show()