wake-up-neo.com

Matplotlib: Transparentes Histogramm mit nicht transparentem Rand

Ich zeichne ein Histogramm auf, und ich habe drei Datensätze, die ich zusammen zeichnen möchte, jeweils mit verschiedenen Farben und Linientypen (gestrichelt, gepunktet usw.). Ich gebe auch etwas Transparenz, um die überlappenden Balken zu sehen .

Der Punkt ist, dass ich möchte, dass der Rand jedes Balkens nicht transparent wird, wie dies beim inneren Teil der Fall ist. Hier ist ein Beispiel:

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 akzeptiert zusätzliche Schlüsselwortargumente, die für matplotlib.patches.Patch an den Konstruktor übergeben werden. Insbesondere können Sie ein fc=-Argument übergeben, mit dem Sie die Patch-Gesichtsfarbe mit einem (R, G, B, A)-Tuple festlegen können, wenn Sie die Histogramme erstellen. Das Ändern des Alpha-Werts der Gesichtsfarbe hat keinen Einfluss auf die Transparenz der Kanten:

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

Ich denke, vielleicht ist die dümmste Lösung die einfachste und beste? Die Histogramme werden einfach umgeformt, ohne innere Farbe und ohne Alpha. Das sollte nur die Histogrammzeilen wiedergeben. 

Außerdem möchten Sie möglicherweise die Möglichkeit vermeiden, dass sich die Linien/Striche/Punkte nicht überlappen, indem Sie sie vollständig aus dem ersten Histogramm entfernen

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()

ohne die zweiten Aufträge sollte der Graph wie eine Figur ohne Grenzen aussehen. Mit den unteren 3 Histogrammbefehlen werden Ränder hinzugefügt, um das Bild unten zu erzeugen. Funktioniert auf Python3.4 Win7 

[Schnitt, weil ich offenbar nicht genug Repräsentanten habe, um Bilder zu posten]

8
ljetibo

Ich brauchte eine Lösung, bei der ich die Farbe nicht explizit einstellen musste, d. H. Ich wollte immer noch den Standardfarbzyklus verwenden. Die folgende Lösung baut auf der Idee von @ ljetibo auf, das Histogramm zweimal zu zeichnen, wobei die Idee von @ ALi_m verwendet wird, um den Zustand des Farbzyklus zu extrahieren:

# 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)

Beachten Sie, dass die Angabe von color=color zusätzlich zu edgecolor erforderlich ist. Andernfalls erhöht der hist-Aufruf den Farbzyklus erneut.

1
bluenote10