xticks pyplot font axessubplot python matplotlib

python - pyplot - Xlabel/ylabel común para las subparcelas de matplotlib



plot title font size matplotlib (6)

Descubrí un método más robusto:

Si conoce los kwargs bottom y top que entraron en una inicialización de GridSpec , o si conoce las posiciones de los bordes de sus ejes en las coordenadas de la Figure , también puede especificar la posición ylabel en las coordenadas de la Figure con alguna fantasía de "transformación". Por ejemplo:

import matplotlib.transforms as mtransforms bottom, top = .1, .9 f, a = plt.subplots(nrows=2, ncols=1, bottom=bottom, top=top) avepos = (bottom+top)/2 a[0].yaxis.label.set_transform(mtransforms.blended_transform_factory( mtransforms.IdentityTransform(), f.transFigure # specify x, y transform )) # changed from default blend (IdentityTransform(), a[0].transAxes) a[0].yaxis.label.set_position((0, avepos)) a[0].set_ylabel(''Hello, world!'')

... y debería ver que la etiqueta todavía se ajusta apropiadamente de izquierda a derecha para evitar solaparse con etiquetas de tictac, como lo hace normalmente, pero ahora se ajustará para estar siempre exactamente entre las subtramas deseadas.

Además, si ni siquiera usa set_position , el ylabel aparecerá por defecto exactamente a la mitad de la figura . Supongo que esto se debe a que cuando finalmente se dibuja la etiqueta, matplotlib usa 0.5 para la coordenada y sin verificar si la transformación de coordenadas subyacente ha cambiado.

Tengo la siguiente trama:

fig,ax = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size)

y ahora me gustaría darle a esta trama etiquetas de eje x comunes y etiquetas de eje y. Con "común", quiero decir que debería haber una etiqueta de eje x grande debajo de toda la grilla de subtramas, y una etiqueta grande de eje y a la derecha. No puedo encontrar nada al respecto en la documentación de plt.subplots , y mis plt.subplots Google sugieren que tengo que hacer un gran plt.subplot(111) para empezar, pero ¿cómo puedo poner mis subtramas 5 * 2 en ese usando plt.subplots ?


Desde el comando:

fig,ax = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size)

Usaste devuelve una tupla que consiste en la figura y una lista de las instancias de los ejes, ya es suficiente para hacer algo como (tenga en cuenta que he cambiado la fig,ax a la fig,axes ):

fig,axes = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size) for ax in axes: ax.set_xlabel(''Common x-label'') ax.set_ylabel(''Common y-label'')

Si desea cambiar algunos detalles de una subtrama específica, puede acceder a ella a través de los axes[i] donde itere sobre sus subtramas.

También podría ser muy útil incluir un

fig.tight_layout()

al final del archivo, antes de plt.show() , para evitar la superposición de etiquetas.


Esto se ve como lo que realmente quieres. Aplica el mismo enfoque de esta respuesta a su caso específico:

import matplotlib.pyplot as plt fig, ax = plt.subplots(nrows=3, ncols=3, sharex=True, sharey=True, figsize=(6, 6)) fig.text(0.5, 0.04, ''common X'', ha=''center'') fig.text(0.04, 0.5, ''common Y'', va=''center'', rotation=''vertical'')


Me encontré con un problema similar al trazar una grilla de gráficos. Los gráficos consistían en dos partes (superior e inferior). Se suponía que la etiqueta y estaba centrada en ambas partes.

No quería usar una solución que depende de conocer la posición en la figura externa (como fig.text ()), así que manipulé la posición y de la función set_ylabel (). Por lo general, es 0.5, en el medio de la trama se agrega. Como el relleno entre las partes (hspace) en mi código era cero, pude calcular el centro de las dos partes con respecto a la parte superior.

import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec # Create outer and inner grid outerGrid = gridspec.GridSpec(2, 3, width_ratios=[1,1,1], height_ratios=[1,1]) somePlot = gridspec.GridSpecFromSubplotSpec(2, 1, subplot_spec=outerGrid[3], height_ratios=[1,3], hspace = 0) # Add two partial plots partA = plt.subplot(somePlot[0]) partB = plt.subplot(somePlot[1]) # No x-ticks for the upper plot plt.setp(partA.get_xticklabels(), visible=False) # The center is (height(top)-height(bottom))/(2*height(top)) # Simplified to 0.5 - height(bottom)/(2*height(top)) mid = 0.5-somePlot.get_height_ratios()[1]/(2.*somePlot.get_height_ratios()[0]) # Place the y-label partA.set_ylabel(''shared label'', y = mid) plt.show()

picture

Desventajas:

  • La distancia horizontal a la trama se basa en la parte superior, las marcas inferiores se pueden extender a la etiqueta.

  • La fórmula no toma espacio entre las partes en cuenta.

  • Lanza una excepción cuando la altura de la parte superior es 0.

Probablemente haya una solución general que tenga en cuenta el relleno entre figuras.


Se verá mejor si reserva espacio para las etiquetas comunes al hacer etiquetas invisibles para la subtrama en la esquina inferior izquierda. También es bueno pasar el tamaño de fuente de rcParams. De esta forma, las etiquetas comunes cambiarán de tamaño con su configuración de rc, y los ejes también se ajustarán para dejar espacio para las etiquetas comunes.

fig_size = [8, 6] fig, ax = plt.subplots(5, 2, sharex=True, sharey=True, figsize=fig_size) # Reserve space for axis labels ax[-1, 0].set_xlabel(''.'', color=(0, 0, 0, 0)) ax[-1, 0].set_ylabel(''.'', color=(0, 0, 0, 0)) # Make common axis labels fig.text(0.5, 0.04, ''common X'', va=''center'', ha=''center'', fontsize=rcParams[''axes.labelsize'']) fig.text(0.04, 0.5, ''common Y'', va=''center'', ha=''center'', rotation=''vertical'', fontsize=rcParams[''axes.labelsize''])


Sin sharex=True, sharey=True , obtienes:

Con eso deberías hacerlo mejor:

fig, axes2d = plt.subplots(nrows=3, ncols=3, sharex=True, sharey=True, figsize=(6,6)) for i, row in enumerate(axes2d): for j, cell in enumerate(row): cell.imshow(np.random.rand(32,32)) plt.tight_layout()

Pero si desea agregar etiquetas adicionales, debe agregarlas solo a los gráficos de bordes:

fig, axes2d = plt.subplots(nrows=3, ncols=3, sharex=True, sharey=True, figsize=(6,6)) for i, row in enumerate(axes2d): for j, cell in enumerate(row): cell.imshow(np.random.rand(32,32)) if i == len(axes2d) - 1: cell.set_xlabel("noise column: {0:d}".format(j + 1)) if j == 0: cell.set_ylabel("noise row: {0:d}".format(i + 1)) plt.tight_layout()

Agregar etiquetas para cada parcela lo arruinaría (tal vez haya una forma de detectar automáticamente etiquetas repetidas, pero no conozco ninguna).