2
votes

Matplotlib: aligner deux axes y autour de zéro

J'ai un tracé avec deux axes y sur un axe x partagé, et je veux les aligner à y = 0 afin de pouvoir dessiner une ligne horizontale pour mettre en évidence la graduation zéro. actuellement les deux axes ne sont pas alignés et je dois tracer deux lignes ce qui est terrible. Comment puis-je y parvenir?

entrez la description de l'image ici


0 commentaires

3 Réponses :


4
votes

En supposant que vous ayez créé les tracés avec un axe partagé, il vous suffit de modifier la plage de y pour qu'elle soit centrée à zéro ou d'avoir un multiplicateur de décalage similaire dans les deux tracés (c'est-à-dire définir ax.set_ylim (-6, 6) pour les deux tracés). Le code suivant est un exemple.

from matplotlib import pyplot as plt
import numpy as np

#Create some Fake Data
x =np.arange(-10,10)
y = x+np.random.rand(20)
y2 = 0.5*x-3.*np.random.rand(20)


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

#First subplot with zero line not even
ax1 = plt.subplot(121)
ax2 = ax1.twinx()

ax1.plot(x,y,c='r')
ax2.plot(x,y2,c='b')

ax1.axhline(0)

#Second Subplot with zero line the same on both axes
ax3 = plt.subplot(122)
ax4 = ax3.twinx()

ax3.plot(x,y,c='r')
ax4.plot(x,y2,c='b')

ax3.axhline(0)

#If you set your limits on both sides to have the same interval you will get the same zero line
ax3.set_ylim(-10,10)
ax4.set_ylim(-6,6)

plt.show()

entrez la description de l'image ici


2 commentaires

Nous devons donc définir manuellement les plages d'axes pour nous assurer qu'elles sont proportionnelles. Pas de possibilité de garder les échelles automatiques mais avec les zéros liés?


Il existe certainement des moyens d'automatiser cela, mais lorsque vous créez l'axe de sous-tracé dans matplotlib, les limites sont définies en fonction de la plage de valeurs. Ainsi, l'automatisation se ferait sur les données et trouverait les meilleurs bords pour garder les lignes zéro identiques.



0
votes

J'ai trouvé cette excellente bibliothèque qui aligne les axes et maintient la mise à l'échelle automatique.

Installez

pip install mpl-axes-aligner

Utilisation

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

x = np.arange(0.0, 30, 0.1)
y1 = 0.1 * x * np.sin(x)
y2 = 0.001*x**3 - 0.03*x**2 + 0.12*x

fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx()

ax1.plot(x, y1, color='blue', label='Plot 1')
ax2.plot(x, y2, color='red', label='Plot 2')

# Align y = 0 of ax1 and ax2 with the center of figure.
mpl_axes_aligner.align.yaxes(ax1, 0, ax2, 0, 0.5)

plt.show()

Sortie

Output graph

Credits

Ce package a été développé par ryotuk et l'exemple d'utilisation ci-dessus provient de la documentation de son paquet.


0 commentaires

0
votes

J'ai eu le même problème, et ce que j'ai fait a été de changer l'étendue de l'axe y, en fonction du rapport des limites min / max. Si vous définissez le rapport des axes y comme étant le même, le point zéro devrait être le même.

fig, ax1 = plt.subplots()

ax1.plot(...)
ax2 = ax1.twinx()
ax2.plot(...)

ax1_ylims = ax1.axes.get_ylim()
ax1_yratio = ax1_ylims[0] / ax1_ylims[1]

ax2_ylims = ax2.axes.get_ylim()
ax2_yratio = ax2_ylims[0] / ax2_ylims[1]

if ax1_yratio < ax2_yratio:
    ax2.set_ylim(bottom = ax2_ylims[1]*ax1_yratio)
else:
    ax1.set_ylim(bottom = ax1_ylims[1]*ax2_yratio)

plt.tight_layout()
plt.show()

Ceci est ma première réponse, donc j'espère que c'est suffisant et correct.


0 commentaires