Python >> Tutoriel Python >  >> Python Tag >> Matplotlib

Comment éviter le chevauchement des barres d'erreur dans matplotlib ?

Vous pouvez traduire chaque barre d'erreur en ajoutant la transformation de données par défaut à une traduction précédente dans l'espace de données. Ceci est possible en sachant que les catégories sont en général à une unité de données les unes des autres.

import numpy as np; np.random.seed(42)
import matplotlib.pyplot as plt
from matplotlib.transforms import Affine2D

x = list("ABCDEF")
y1, y2 = np.random.randn(2, len(x))
yerr1, yerr2 = np.random.rand(2, len(x))*4+0.3

fig, ax = plt.subplots()

trans1 = Affine2D().translate(-0.1, 0.0) + ax.transData
trans2 = Affine2D().translate(+0.1, 0.0) + ax.transData
er1 = ax.errorbar(x, y1, yerr=yerr1, marker="o", linestyle="none", transform=trans1)
er2 = ax.errorbar(x, y2, yerr=yerr2, marker="o", linestyle="none", transform=trans2)

plt.show()

Alternativement, vous pouvez traduire les barres d'erreur après avoir appliqué la transformation des données et donc les déplacer en unités de points.

import numpy as np; np.random.seed(42)
import matplotlib.pyplot as plt
from matplotlib.transforms import ScaledTranslation

x = list("ABCDEF")
y1, y2 = np.random.randn(2, len(x))
yerr1, yerr2 = np.random.rand(2, len(x))*4+0.3

fig, ax = plt.subplots()

trans1 = ax.transData + ScaledTranslation(-5/72, 0, fig.dpi_scale_trans)
trans2 = ax.transData + ScaledTranslation(+5/72, 0, fig.dpi_scale_trans)
er1 = ax.errorbar(x, y1, yerr=yerr1, marker="o", linestyle="none", transform=trans1)
er2 = ax.errorbar(x, y2, yerr=yerr2, marker="o", linestyle="none", transform=trans2)

plt.show()

Bien que les résultats semblent similaires dans les deux cas, ils sont fondamentalement différents. Vous observerez cette différence lors d'un zoom interactif sur les axes ou de la modification de la taille de la figure.


Considérez l'approche suivante pour mettre en surbrillance les tracés - combinaison de errorbar et fill_between avec une transparence non nulle :

import random
import matplotlib.pyplot as plt

# create sample data
N = 8
data_1 = {
    'x': list(range(N)),
    'y': [10. + random.random() for dummy in range(N)],
    'yerr': [.25 + random.random() for dummy in range(N)]}
data_2 = {
    'x': list(range(N)),
    'y': [10.25 + .5 * random.random() for dummy in range(N)],
    'yerr': [.5 * random.random() for dummy in range(N)]}

# plot
plt.figure()
# only errorbar
plt.subplot(211)
for data in [data_1, data_2]:
    plt.errorbar(**data, fmt='o')
# errorbar + fill_between
plt.subplot(212)
for data in [data_1, data_2]:
    plt.errorbar(**data, alpha=.75, fmt=':', capsize=3, capthick=1)
    data = {
        'x': data['x'],
        'y1': [y - e for y, e in zip(data['y'], data['yerr'])],
        'y2': [y + e for y, e in zip(data['y'], data['yerr'])]}
    plt.fill_between(**data, alpha=.25)

Résultat :