web-dev-qa-db-fra.com

Matplotlib: histogramme en traçage transparent avec bord non transparent

Je suis en train de tracer un histogramme et j'ai trois jeux de données que je veux tracer ensemble, chacun avec des couleurs et un type de ligne différents (pointillé, pointillé, etc.) Je donne également une certaine transparence, afin de voir les barres qui se chevauchent .

Le fait est que je voudrais que le bord de chaque barre ne devienne pas transparent comme le fait la partie intérieure ..___. Voici un exemple:

import matplotlib.pyplot as plt
import numpy as np

x = np.random.random(20)
y =np.random.random(20)
z= np.random.random(20)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.hist(x, bins=np.arange(0, 1, 0.1), ls='dashed', alpha = 0.5, lw=3, color= 'b')
ax.hist(y, bins=np.arange(0, 1, 0.1), ls='dotted', alpha = 0.5, lw=3, color= 'r')
ax.hist(z, bins=np.arange(0, 1, 0.1), alpha = 0.5, lw=3, color= 'k')
ax.set_xlim(-0.5, 1.5)
ax.set_ylim(0, 7)
plt.show()

enter image description here

23
Argentina

plt.hist accepte les arguments de mot clé supplémentaires transmis au constructeur pour matplotlib.patches.Patch . En particulier, vous pouvez passer un argument fc= qui vous permet de définir la couleur de façade du patch à l'aide d'un tuple (R, G, B, A) lors de la création des histogrammes. La modification de la valeur alpha de la couleur de façade n’affecte pas la transparence des bords:

ax.hist(x, bins=np.arange(0, 1, 0.1), ls='dashed', lw=3, fc=(0, 0, 1, 0.5))
ax.hist(y, bins=np.arange(0, 1, 0.1), ls='dotted', lw=3, fc=(1, 0, 0, 0.5))
ax.hist(z, bins=np.arange(0, 1, 0.1), lw=3, fc=(0, 0, 0, 0.5))

enter image description here

21
ali_m

Je pense que la solution la plus simple est peut-être la plus facile et la meilleure? Il suffit de repasser les histogrammes, sans couleur intérieure et sans alpha. Cela devrait replacer uniquement les lignes de l'histogramme. 

De plus, vous voudrez peut-être éviter que les lignes, les tirets et les points ne se chevauchent pas en les supprimant complètement du premier tracé de l'histogramme.

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

x = np.random.random(20)
y = np.random.random(20)
z = np.random.random(20)

fig = plt.figure()
ax = fig.add_subplot(111)

ax.hist(x, bins=np.arange(0, 1, 0.1), edgecolor='None', alpha = 0.5, color= 'b')
ax.hist(y, bins=np.arange(0, 1, 0.1), edgecolor='None', alpha = 0.5, color= 'r')
ax.hist(z, bins=np.arange(0, 1, 0.1), edgecolor="None", alpha = 0.5, color= 'k')


ax.hist(x, bins=np.arange(0, 1, 0.1), ls='dashed', lw=3, facecolor="None")
ax.hist(y, bins=np.arange(0, 1, 0.1), ls='dotted', lw=3, facecolor="None")
ax.hist(z, bins=np.arange(0, 1, 0.1), lw=3, facecolor="None")

plt.show()

sans les deuxièmes ordres, le graphique devrait ressembler à votre figure sans aucune bordure. Avec les 3 commandes en bas de l'histogramme, des bordures sont ajoutées pour produire l'image ci-dessous. Fonctionne sur Python3.4 Win7 

[coupé parce qu'apparemment je n'ai pas assez de représentant pour poster des photos]

8
ljetibo

J'avais besoin d'une solution qui ne m'obligeait pas à définir explicitement la couleur, c'est-à-dire que je voulais toujours utiliser le cycle de couleur par défaut. La solution suivante s'appuie sur l'idée de @ ljetibo de dessiner l'histogramme deux fois en utilisant l'idée de @ ALi_m pour extraire l'état du cycle de couleur:

# increment and get the "props" cycle (and extract the color)
color = next(ax._get_lines.prop_cycler)["color"]
# 1. draw: inner area with alpha
ax.hist(data, color=color, alpha=0.3)
# 2. draw: only edges with full color
ax.hist(data, color=color, edgecolor=color, fc="None", lw=1)

Notez que spécifier color=color en plus de edgecolor semble être nécessaire. Sinon, l'appel hist incrémentera à nouveau le cycle de couleur.

1
bluenote10