Actualmente estoy usando matplotlib para trazar una medición contra 2 o 3 otras medidas (a veces categóricas) en el eje x. Actualmente, estoy agrupando los datos en el eje x en tuplas y ordenándolos antes de trazar ... el resultado se parece a la imagen de la izquierda a continuación. Lo que me gustaría hacer es trazar los datos con múltiples ejes x como puede ver en la imagen de la derecha. La agrupación de las etiquetas del "eje x de tratamiento" sería la guinda del pastel.¿Cómo grafico múltiples ejes X o Y en matplotlib?
22
A
Respuesta
19
En primer lugar, pregunta cool! Definitivamente es posible con matplotlib> = 1.0.0. (La nueva funcionalidad de espinas lo permite)
Se requiere un poco de vudú, aunque ... Mi ejemplo es lejos de ser perfecto, pero espero que tiene cierto sentido:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
def main():
#-- Generate some data ----------------------------------------------------
nx = 10
x = np.linspace(0, 2*np.pi, 10)
y = 2 * np.sin(x)
groups = [('GroupA', (x[0], x[nx//3])),
('GroupB', (x[-2*nx//3], x[2*nx//3])),
('GroupC', (x[-nx//3], x[-1]))]
#-- Plot the results ------------------------------------------------------
fig = plt.figure()
ax = fig.add_subplot(111)
# Give ourselves a bit more room at the bottom
plt.subplots_adjust(bottom=0.2)
ax.plot(x,y, 'k^')
# Drop the bottom spine by 40 pts
ax.spines['bottom'].set_position(('outward', 40))
# Make a second bottom spine in the position of the original bottom spine
make_second_bottom_spine(label='Treatment')
# Annotate the groups
for name, xspan in groups:
annotate_group(name, xspan)
plt.xlabel('Dose')
plt.ylabel('Response')
plt.title('Experimental Data')
plt.show()
def annotate_group(name, xspan, ax=None):
"""Annotates a span of the x-axis"""
def annotate(ax, name, left, right, y, pad):
arrow = ax.annotate(name,
xy=(left, y), xycoords='data',
xytext=(right, y-pad), textcoords='data',
annotation_clip=False, verticalalignment='top',
horizontalalignment='center', linespacing=2.0,
arrowprops=dict(arrowstyle='-', shrinkA=0, shrinkB=0,
connectionstyle='angle,angleB=90,angleA=0,rad=5')
)
return arrow
if ax is None:
ax = plt.gca()
ymin = ax.get_ylim()[0]
ypad = 0.01 * np.ptp(ax.get_ylim())
xcenter = np.mean(xspan)
left_arrow = annotate(ax, name, xspan[0], xcenter, ymin, ypad)
right_arrow = annotate(ax, name, xspan[1], xcenter, ymin, ypad)
return left_arrow, right_arrow
def make_second_bottom_spine(ax=None, label=None, offset=0, labeloffset=20):
"""Makes a second bottom spine"""
if ax is None:
ax = plt.gca()
second_bottom = mpl.spines.Spine(ax, 'bottom', ax.spines['bottom']._path)
second_bottom.set_position(('outward', offset))
ax.spines['second_bottom'] = second_bottom
if label is not None:
# Make a new xlabel
ax.annotate(label,
xy=(0.5, 0), xycoords='axes fraction',
xytext=(0, -labeloffset), textcoords='offset points',
verticalalignment='top', horizontalalignment='center')
if __name__ == '__main__':
main()
9
El ejemplo de Joe es bueno. También arrojaré el mío. Estuve trabajando en ello hace unas horas, pero luego tuve que salir corriendo a una reunión. Roba de here.
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
## the following two functions override the default behavior or twiny()
def make_patch_spines_invisible(ax):
ax.set_frame_on(True)
ax.patch.set_visible(False)
for sp in ax.spines.itervalues():
sp.set_visible(False)
def make_spine_invisible(ax, direction):
if direction in ["right", "left"]:
ax.yaxis.set_ticks_position(direction)
ax.yaxis.set_label_position(direction)
elif direction in ["top", "bottom"]:
ax.xaxis.set_ticks_position(direction)
ax.xaxis.set_label_position(direction)
else:
raise ValueError("Unknown Direction : %s" % (direction,))
ax.spines[direction].set_visible(True)
data = (('A',0.01),('A',0.02),('B',0.10),('B',0.20)) # fake data
fig = plt.figure(1)
sb = fig.add_subplot(111)
sb.xaxis.set_major_locator(ticker.FixedLocator([0,1,2,3]))
sb.plot([i[1] for i in data],"*",markersize=10)
sb.set_xlabel("dose")
plt.subplots_adjust(bottom=0.17) # make room on bottom
par2 = sb.twiny() # create a second axes
par2.spines["bottom"].set_position(("axes", -.1)) # move it down
## override the default behavior for a twiny axis
make_patch_spines_invisible(par2)
make_spine_invisible(par2, "bottom")
par2.set_xlabel("treatment")
par2.plot([i[1] for i in data],"*",markersize=10) #redraw to put twiny on same scale
par2.xaxis.set_major_locator(ticker.FixedLocator([0,1,2,3]))
par2.xaxis.set_ticklabels([i[0] for i in data])
plt.show()
Produce:
Cuestiones relacionadas
- 1. matplotlib vinculados x ejes con ejes y de escalado automático en el zoom
- 2. PANDAS traza múltiples ejes Y
- 3. Cómo cambiar los ejes en matplotlib?
- 4. Diferencia entre "ejes" y "eje" en matplotlib?
- 5. matplotlib: ejes insertados para múltiples diagramas de caja
- 6. ejes no lineales para imshow en matplotlib
- 7. ¿Cómo puedo ocultar los ejes en matplotlib 3d?
- 8. matplotlib: agregar segundos ejes() con fondo transparente?
- 9. ¿Cómo grafico de una función de paso con Matplotlib en Python?
- 10. Windows Form C# Gráfico Ejes Etiqueta en los ejes X e Y
- 11. Cómo escalar ejes en mplot3d
- 12. Dibujar líneas de ejes o el origen de la gráfica de contorno de Matplotlib
- 13. set_data y autoscale_view matplotlib
- 14. Trazar los ejes logarítmicos con matplotlib en python
- 15. ¿Cómo agrego espacio entre las etiquetas ticklabels y los ejes en matplotlib?
- 16. Rasterización de elementos múltiples en matplotlib
- 17. Python Matplotlib figura título se superpone etiqueta ejes utilizando Twiny
- 18. ¿Cómo grafico una barra apilada con ggplot?
- 19. JavaScript Chart Library con varios ejes X e Y, y valores de eje negativo
- 20. matplotlib: selecciona interactivamente puntos o ubicaciones?
- 21. Matplotlib Unicode etiquetas de los ejes utilizando el renderizador Cairo
- 22. Gráficos de Matplotlib: eliminación de ejes, leyendas y espacios en blanco
- 23. Personalice el eje x en matplotlib
- 24. Cambio x nueva escala en matplotlib
- 25. Encontrar los ángulos para los ejes X, Y y Z en 3D - OpenGL/C++
- 26. Emacs, GDB y Windows X múltiples
- 27. Cómo agregar un segundo eje x en matplotlib
- 28. Emacs 23 en OS X: ¿usar instancias múltiples o emacsclient?
- 29. python y actualizar figura en matplotlib
- 30. Matplotlib: trazado simultáneo en múltiples hilos
estoy familiarizado con este vudú - cuidado para mostrar cómo generalizar esto a ejes más categóricas? Pensé que crear un tercer lomo inferior con algo de compensación lo haría visible, pero eso no funciona para mí, todavía está apilado justo encima del segundo. (Puedo abrir una nueva pregunta si eso es posible) – Thomas
nm Lo tengo ahora; aunque también me gustaría ver su implementación (más limpia). – Thomas