So geben Sie einem Pandas / Matplotlib-Balkendiagramm benutzerdefinierte Farben

84

Ich habe gerade angefangen, pandas / matplotlib als Ersatz für Excel zu verwenden, um gestapelte Balkendiagramme zu generieren. Ich stoße auf ein Problem

(1) Die Standard-Farbkarte enthält nur 5 Farben. Wenn ich also mehr als 5 Kategorien habe, wiederholen sich die Farben. Wie kann ich mehr Farben angeben? Idealerweise ein Farbverlauf mit einer Start- und einer Endfarbe sowie eine Möglichkeit, dazwischen dynamisch n Farben zu generieren?

(2) Die Farben sind optisch nicht sehr ansprechend. Wie gebe ich einen benutzerdefinierten Satz von n Farben an? Oder ein Farbverlauf würde auch funktionieren.

Ein Beispiel, das beide oben genannten Punkte veranschaulicht, ist unten:

  4 from matplotlib import pyplot
  5 from pandas import *
  6 import random
  7 
  8 x = [{i:random.randint(1,5)} for i in range(10)]
  9 df = DataFrame(x)
 10 
 11 df.plot(kind='bar', stacked=True)

Und die Ausgabe ist folgende:

Geben Sie hier die Bildbeschreibung ein

vasek1
quelle
Es gibt eine ziemlich einfache Möglichkeit, eine teilweise Farbkarte zu erhalten. Siehe diese Lösung unten
Ted Petrou

Antworten:

117

Sie können die colorOption als Liste direkt für die plotFunktion angeben .

from matplotlib import pyplot as plt
from itertools import cycle, islice
import pandas, numpy as np  # I find np.random.randint to be better

# Make the data
x = [{i:np.random.randint(1,5)} for i in range(10)]
df = pandas.DataFrame(x)

# Make a list by cycling through the colors you care about
# to match the length of your data.
my_colors = list(islice(cycle(['b', 'r', 'g', 'y', 'k']), None, len(df)))

# Specify this list of colors as the `color` option to `plot`.
df.plot(kind='bar', stacked=True, color=my_colors)

Um Ihre eigene benutzerdefinierte Liste zu definieren, können Sie einige der folgenden Schritte ausführen oder einfach die Matplotlib-Techniken zum Definieren eines Farbelements anhand seiner RGB-Werte usw. nachschlagen. Sie können damit so kompliziert werden, wie Sie möchten.

my_colors = ['g', 'b']*5 # <-- this concatenates the list to itself 5 times.
my_colors = [(0.5,0.4,0.5), (0.75, 0.75, 0.25)]*5 # <-- make two custom RGBs and repeat/alternate them over all the bar elements.
my_colors = [(x/10.0, x/20.0, 0.75) for x in range(len(df))] # <-- Quick gradient example along the Red/Green dimensions.

Das letzte Beispiel ergibt für mich den folgenden einfachen Farbverlauf:

Geben Sie hier die Bildbeschreibung ein

Ich habe nicht lange genug damit gespielt, um herauszufinden, wie man die Legende dazu zwingt, die definierten Farben aufzunehmen, aber ich bin sicher, dass Sie es schaffen können.

Im Allgemeinen ist es jedoch ein großer Ratschlag, die Funktionen von Matplotlib direkt zu verwenden. Es ist in Ordnung, sie von Pandas aus anzurufen, aber ich finde, Sie erhalten bessere Optionen und eine bessere Leistung, wenn Sie sie direkt von Matplotlib aus anrufen.

ely
quelle
3
Kleiner Fehler: my_colors = [Zyklus (['b', 'r', 'g', 'y', 'k']). Next () für i im Bereich (len (df))] gibt 'b'. jedes Mal in Python 2.7. Sie sollten stattdessen list (islice (Zyklus (['b', 'r', 'g', 'y', 'k']), None, len (df)) verwenden.
vkontori
Danke, das hätte ich wahrscheinlich nicht verstanden. Eine andere Möglichkeit besteht darin, zuerst den Zyklus zu erstellen und dann seine nextFunktion innerhalb des Verständnisses aufzurufen .
Ely
Jep. it = Zyklus (['b', 'r', 'g', 'y', 'k']); my_colors = [next (it) für i in xrange (len (df))] würde es auch schneiden ...
vkontori
1
Mit Pandas und Matplotlib, die heute installiert sind, generiert der obige Code nichts für mich, obwohl er ausgeführt wird.
Kakyo
@kakyo Laufen Sie im regulären Interpreter IPython oder über die Shell (oder etwas anderes)? Je nachdem, in welcher Umgebung Sie diesen Code ausführen, müssen Sie möglicherweise den interaktiven Modus für matplotlib aktivieren oder pylab.ion()für interaktives Pylab festlegen.
Ely
52

Ich fand, dass es am einfachsten ist, den colormapParameter .plot()mit einem der voreingestellten Farbverläufe zu verwenden:

df.plot(kind='bar', stacked=True, colormap='Paired')

Geben Sie hier die Bildbeschreibung ein

Eine große Liste voreingestellter Farbkarten finden Sie hier .

Farbkarten

Alexandre
quelle
18
in meinem Fall ergibt dies nur eine Farbe über alle Balken
Tsando
15

Für eine detailliertere Antwort zum Erstellen eigener Farbkarten empfehle ich dringend, diese Seite zu besuchen

Wenn diese Antwort zu viel Arbeit ist, können Sie schnell eine eigene Liste von Farben erstellen und diese an den colorParameter übergeben. Alle Farbkarten befinden sich im cmmatplotlib-Modul. Lassen Sie uns eine Liste mit 30 RGB-Farbwerten (plus Alpha) aus der umgekehrten Inferno-Farbkarte abrufen. Holen Sie sich dazu zuerst die Farbkarte und übergeben Sie ihr dann eine Folge von Werten zwischen 0 und 1. Hier np.linspaceerstellen wir 30 Werte mit gleichem Abstand zwischen 0,4 und 0,8, die diesen Teil der Farbkarte darstellen.

from matplotlib import cm
color = cm.inferno_r(np.linspace(.4, .8, 30))
color

array([[ 0.865006,  0.316822,  0.226055,  1.      ],
       [ 0.851384,  0.30226 ,  0.239636,  1.      ],
       [ 0.832299,  0.283913,  0.257383,  1.      ],
       [ 0.817341,  0.270954,  0.27039 ,  1.      ],
       [ 0.796607,  0.254728,  0.287264,  1.      ],
       [ 0.775059,  0.239667,  0.303526,  1.      ],
       [ 0.758422,  0.229097,  0.315266,  1.      ],
       [ 0.735683,  0.215906,  0.330245,  1.      ],
       .....

Dann können wir dies verwenden, um unter Verwendung der Daten aus dem ursprünglichen Beitrag zu zeichnen:

import random
x = [{i: random.randint(1, 5)} for i in range(30)]
df = pd.DataFrame(x)
df.plot(kind='bar', stacked=True, color=color, legend=False, figsize=(12, 4))

Geben Sie hier die Bildbeschreibung ein

Ted Petrou
quelle
2
Hier ist die Dokumentation zu anderen Farbkarten außer inferno_r: matplotlib.org/examples/color/colormaps_reference.html
Tsando
1
Ich bin diesem Snippet gefolgt, aber mein Farbarray hat immer die gleichen Werte.
FaCoffee