Ich zeichne mehrere Linien in einer einzigen Grafik und möchte, dass sie durch das Spektrum einer Farbkarte laufen, nicht nur durch die gleichen 6 oder 7 Farben. Der Code ist dem ähnlich:
for i in range(20):
for k in range(100):
y[k] = i*x[i]
plt.plot(x,y)
plt.show()
Sowohl mit Colormap "Jet" als auch mit einer anderen, die ich von Seaborn importiert habe, bekomme ich die gleichen 7 Farben in derselben Reihenfolge wiederholt. Ich möchte bis zu ~ 60 verschiedene Linien mit unterschiedlichen Farben zeichnen können.
Die Matplotlib-Colormaps akzeptieren ein Argument (0..1
, Skalar oder Array), mit dem Sie Farben aus einer Colormap erhalten. Zum Beispiel:
col = pl.cm.jet([0.25,0.75])
Gibt Ihnen ein Array mit (zwei) RGBA-Farben:
array ([[0., 0.50392157, 1., 1.], [1., 0.58169935, 0., 1.]])
Sie können das verwenden, um N
verschiedene Farben zu erstellen:
import numpy as np
import matplotlib.pylab as pl
x = np.linspace(0, 2*np.pi, 64)
y = np.cos(x)
pl.figure()
pl.plot(x,y)
n = 20
colors = pl.cm.jet(np.linspace(0,1,n))
for i in range(n):
pl.plot(x, i*y, color=colors[i])
Barts Lösung ist nett und einfach, hat aber zwei Mängel.
plt.colorbar()
funktioniert nicht auf nette Art und Weise, da die Liniendiagramme nicht zugeordnet werden können (verglichen mit einem Bild).
Bei einer großen Anzahl von Zeilen kann es aufgrund der for-Schleife langsam sein (obwohl dies für die meisten Anwendungen vielleicht kein Problem ist?)
Diese Probleme können mit LineCollection
behoben werden. Dies ist meiner Meinung nach jedoch nicht zu benutzerfreundlich. Es gibt einen offenen Vorschlag auf GitHub , um eine mehrfarbige Liniendiagrammfunktion hinzuzufügen, ähnlich der Funktion plt.scatter(...)
.
Hier ist ein Arbeitsbeispiel, das ich zusammen hacken konnte
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
def multiline(xs, ys, c, ax=None, **kwargs):
"""Plot lines with different colorings
Parameters
----------
xs : iterable container of x coordinates
ys : iterable container of y coordinates
c : iterable container of numbers mapped to colormap
ax (optional): Axes to plot on.
kwargs (optional): passed to LineCollection
Notes:
len(xs) == len(ys) == len(c) is the number of line segments
len(xs[i]) == len(ys[i]) is the number of points for each line (indexed by i)
Returns
-------
lc : LineCollection instance.
"""
# find axes
ax = plt.gca() if ax is None else ax
# create LineCollection
segments = [np.column_stack([x, y]) for x, y in Zip(xs, ys)]
lc = LineCollection(segments, **kwargs)
# set coloring of line segments
# Note: I get an error if I pass c as a list here... not sure why.
lc.set_array(np.asarray(c))
# add lines to axes and rescale
# Note: adding a collection doesn't autoscalee xlim/ylim
ax.add_collection(lc)
ax.autoscale()
return lc
Hier ist ein sehr einfaches Beispiel:
xs = [[0, 1],
[0, 1, 2]]
ys = [[0, 0],
[1, 2, 1]]
c = [0, 1]
lc = multiline(xs, ys, c, cmap='bwr', lw=2)
Produziert:
Und etwas anspruchsvoller:
n_lines = 30
x = np.arange(100)
yint = np.arange(0, n_lines*10, 10)
ys = np.array([x + b for b in yint])
xs = np.array([x for i in range(n_lines)]) # could also use np.tile
colors = np.arange(n_lines)
fig, ax = plt.subplots()
lc = multiline(xs, ys, yint, cmap='bwr', lw=2)
axcb = fig.colorbar(lc)
axcb.set_label('Y-intercept')
ax.set_title('Line Collection with mapped colors')
Produziert:
Hoffe das hilft!
Eine Alternative zu Barts Antwort, in der Sie nicht die Farbe in jedem Aufruf von plt.plot
angeben, besteht darin, mit set_prop_cycle
einen neuen Farbzyklus zu definieren. Sein Beispiel kann in den folgenden Code übersetzt werden (ich habe auch den Import von matplotlib in den empfohlenen Stil geändert):
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2*np.pi, 64)
y = np.cos(x)
n = 20
ax = plt.axes()
ax.set_prop_cycle('color',[plt.cm.jet(i) for i in np.linspace(0, 1, n)])
for i in range(n):
plt.plot(x, i*y)
Wenn Sie kontinuierliche Farbpaletten wie brg, hsv, jet oder die Standardpalette verwenden, können Sie dies wie folgt tun:
color = plt.cm.hsv(r) # r is 0 to 1 inclusive
Jetzt können Sie diesen Farbwert an eine beliebige API übergeben, die Sie wie folgt wünschen:
line = matplotlib.lines.Line2D(xdata, ydata, color=color)