Balkendiagramm in Matplotlib mit einer Farbkarte
Ich habe eine df mit zwei Spalten:
- y: verschiedene numerische Werte für die y-Achse
- Tage: die Namen von vier verschiedenen Tagen (Montag, Dienstag, Mittwoch, Donnerstag)
Ich habe auch eine Farbkarte mit vier verschiedenen Farben, die ich selbst erstellt habe, und es ist ein ListedColorMap-Objekt.
Ich möchte ein Balkendiagramm mit den vier Kategorien (Wochentagen) auf der x-Achse und den entsprechenden Werten auf der y-Achse erstellen. Gleichzeitig möchte ich, dass jeder Balken mithilfe meiner Farbkarte eine andere Farbe hat.
Dies ist der Code, mit dem ich mein Balkendiagramm erstellt habe:
def my_barchart(my_df, my_cmap):
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
ax.bar(my_df['days'], my_df['y'], color=my_cmap)
return fig
Ich erhalte jedoch die folgende Fehlermeldung: "Objekt vom Typ 'ListedColormap' hat kein len ()", daher scheint es, dass ich my_cmap nicht richtig verwende.
Wenn ich das aus der Funktion entferne und ausführe, sieht mein Balkendiagramm in Ordnung aus, außer dass alle Balken dieselbe Farbe haben. Meine Frage lautet also: Wie kann man eine Farbkarte mit einem Balkendiagramm richtig verwenden?
Antworten
The color argument wants either a string or an RGB[A] value (it can be a single colour, or a sequence of colours with one for each data point you are plotting). Colour maps are typically callable with floats in the range [0, 1].
So what you want to do is take the values you want for the colours for each bar, scale them to the range [0, 1], and then call my_cmap with those rescaled values.
So, say for example you wanted the colours to correspond to the y values (heights of the bars), then you should modify your code like this (assumes you have called import numpy as np earlier on):
def my_barchart(my_df, my_cmap):
rescale = lambda y: (y - np.min(y)) / (np.max(y) - np.min(y))
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
ax.bar(my_df['days'], my_df['y'], color=my_cmap(rescale(my_df['y'])))
return fig
Here is a self-contained minimal example of using the color argument with the output from a cmap:
import matplotlib.pyplot as plt
import numpy as np
x = np.array([1, 2, 3])
y = np.array([4, 5, 6])
my_cmap = plt.get_cmap("viridis")
rescale = lambda y: (y - np.min(y)) / (np.max(y) - np.min(y))
plt.bar(x, y, color=my_cmap(rescale(y)))
plt.savefig("temp")
Output:
Okay, I found a way to do this without having to scale my values:
def my_barchart(my_df, my_cmap):
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
ax.bar(my_df['days'], my_df['y'], color=my_cmap.colors)
return fig
Simply adding .colors after my_cmap works!