Quiero 3 gráficos en un objeto de ejes, por ejemplo:
#example x- and y-data x_values1=[1,2,3,4,5] y_values1=[1,2,3,4,5] x_values2=[-1000,-800,-600,-400,-200] y_values2=[10,20,39,40,50] x_values3=[150,200,250,300,350] y_values3=[10,20,30,40,50] #make axes fig=plt.figure() ax=fig.add_subplot(111)
ahora quiero agregar los tres conjuntos de datos a ax. Pero no deberían compartir ningún eje x o y (ya que, debido a las diferentes escalas, uno sería mucho más pequeño que el otro. Necesito algo como ax.twinx(), ax.twiny(), pero tanto el x - y el eje y deben ser independientes.
Quiero hacer esto, porque quiero poner las dos parcelas adjuntas (y una tercera, que es similar a la segunda) en una parcela ("ponerlas una encima de la otra"). Parcela1 Parcela2
Luego pondría las etiquetas x/y (y/o marcas, límites) de la segunda gráfica en la parte superior derecha/arriba y los límites x/y de otra gráfica en la parte inferior/izquierda. No necesito etiquetas x/y de la trama 3.
¿Cómo hago esto?
La idea sería crear tres subtramas en la misma posición. Para asegurarse, se reconocerán como gráficos diferentes, sus propiedades deben diferir, y la forma más fácil de lograrlo es simplemente proporcionar una etiqueta diferente, ax=fig.add_subplot(111, label="1")
.
El resto es simplemente ajustar todos los parámetros de los ejes, de modo que la trama resultante se vea atractiva. Es un poco de trabajo configurar todos los parámetros, pero lo siguiente debería hacer lo que necesita.
import matplotlib.pyplot as plt x_values1=[1,2,3,4,5] y_values1=[1,2,2,4,1] x_values2=[-1000,-800,-600,-400,-200] y_values2=[10,20,39,40,50] x_values3=[150,200,250,300,350] y_values3=[10,20,30,40,50] fig=plt.figure() ax=fig.add_subplot(111, label="1") ax2=fig.add_subplot(111, label="2", frame_on=False) ax3=fig.add_subplot(111, label="3", frame_on=False) ax.plot(x_values1, y_values1, color="C0") ax.set_xlabel("x label 1", color="C0") ax.set_ylabel("y label 1", color="C0") ax.tick_params(axis='x', colors="C0") ax.tick_params(axis='y', colors="C0") ax2.scatter(x_values2, y_values2, color="C1") ax2.xaxis.tick_top() ax2.yaxis.tick_right() ax2.set_xlabel('x label 2', color="C1") ax2.set_ylabel('y label 2', color="C1") ax2.xaxis.set_label_position('top') ax2.yaxis.set_label_position('right') ax2.tick_params(axis='x', colors="C1") ax2.tick_params(axis='y', colors="C1") ax3.plot(x_values3, y_values3, color="C3") ax3.set_xticks([]) ax3.set_yticks([]) plt.show()
También puede estandarizar los datos para que compartan los mismos límites y luego trazar los límites de la segunda escala deseada "manualmente". Esta función estandariza los datos hasta los límites del primer conjunto de puntos:
def standardize(data): for a in range(2): span = max(data[0][a]) - min(data[0][a]) min_ = min(data[0][a]) for idx in range(len(data)): standardize = (max(data[idx][a]) - min(data[idx][a]))/span data[idx][a] = [i/standardize + min_ - min([i/standardize for i in data[idx][a]]) for i in data[idx][a]] return data
Entonces, graficar los datos es fácil:
import matplotlib.pyplot as plt data = [[[1,2,3,4,5],[1,2,2,4,1]], [[-1000,-800,-600,-400,-200], [10,20,39,40,50]], [[150,200,250,300,350], [10,20,30,40,50]]] limits = [(min(data[1][a]), max(data[1][a])) for a in range(2)] norm_data = standardize(data) fig, ax = plt.subplots() for x, y in norm_data: ax.plot(x, y) ax2, ax3 = ax.twinx(), ax.twiny() ax2.set_ylim(limits[1]) ax3.set_xlim(limits[0]) plt.show()
Dado que todos los puntos de datos tienen los límites del primer conjunto de puntos, podemos trazarlos en el mismo eje. Luego, usando los límites del segundo eje x e y deseado, podemos establecer los límites para estos dos.
En este ejemplo, puede trazar varias líneas en cada eje xy y escribir legend
en cada línea.
import numpy as np import matplotlib.pyplot as plt X1 = np.arange(10) X1 = np.stack([X1, X1]) Y1 = np.random.randint(1, 10, (2, 10)) X2 = np.arange(0, 1000, 200) X2 = np.stack([X2, X2]) Y2 = np.random.randint(100, 200, (2, 5)) x_label_names = ['XXX', 'xxx'] y_label_names = ['YYY', 'yyy'] X1_legend_names = ['X1_legend1', 'X1_legend2'] X2_legend_names = ['X2_legend1', 'X2_legend2'] def plot_by_two_xaxis(X1, Y1, X2, Y2, x_label_names: list, y_label_names: list, X1_legend_names: list, X2_legend_names: list): fig = plt.figure() ax1s = [] ax2s = [] lines = [] j = 0 for i in range(len(X1)): j += 1 ax1s.append(fig.add_subplot(111, label=f"{j}", frame_on=(j == 1))) for i in range(len(X2)): j += 1 ax2s.append(fig.add_subplot(111, label=f"{j}", frame_on=(j == 1))) k = 0 for i in range(len(X1)): lines.append(ax1s[i].plot(X1[i], Y1[i], color=f"C{k}")[0]) if i == 0: ax1s[i].set_xlabel(x_label_names[0], color=f"C{k}") ax1s[i].set_ylabel(y_label_names[0], color=f"C{k}") ax1s[i].tick_params(axis='x', colors=f"C{k}") ax1s[i].tick_params(axis='y', colors=f"C{k}") else: ax1s[i].set_xticks([]) ax1s[i].set_yticks([]) k += 1 for i in range(len(X1)): lines.append(ax2s[i].plot(X2[i], Y2[i], color=f"C{k}")[0]) if i == 0: ax2s[i].xaxis.tick_top() ax2s[i].yaxis.tick_right() ax2s[i].set_xlabel(x_label_names[1], color=f"C{k}") ax2s[i].set_ylabel(y_label_names[1], color=f"C{k}") ax2s[i].xaxis.set_label_position('top') ax2s[i].yaxis.set_label_position('right') ax2s[i].tick_params(axis='x', colors=f"C{k}") ax2s[i].tick_params(axis='y', colors=f"C{k}") else: ax2s[i].set_xticks([]) ax2s[i].set_yticks([]) k += 1 ax1s[0].legend(lines, X1_legend_names + X2_legend_names) plt.show() plot_by_two_xaxis(X1, Y1, X2, Y2, x_label_names, y_label_names, X1_legend_names, X2_legend_names)