Zeichnen Sie mit matplotlib verschiedene Farben für verschiedene kategoriale Ebenen


101

Ich habe diesen Datenrahmen, diamondsder sich aus Variablen wie zusammensetzt (carat, price, color), und ich möchte für jeden ein Streudiagramm von pricebis zeichnen , was bedeutet, dass verschiedene unterschiedliche Farben im Diagramm haben.caratcolorcolor

Dies ist leicht in Rmit ggplot:

ggplot(aes(x=carat, y=price, color=color),  #by setting color=color, ggplot automatically draw in different colors
       data=diamonds) + geom_point(stat='summary', fun.y=median)

Geben Sie hier die Bildbeschreibung ein

Ich frage mich, wie das in Python mit gemacht werden könnte matplotlib.

PS:

Ich kenne mich mit zusätzlichen Plot- Paketen wie seabornund aus ggplot for python, und ich bevorzuge sie nicht. Ich möchte nur herausfinden, ob es möglich ist, die Arbeit matplotliballeine zu erledigen


1
Es wäre wirklich schön, so etwas in matplotlib eingebaut zu haben, aber es hört sich so an, als wäre es nicht einfach. Diskussion hier: github.com/matplotlib/matplotlib/issues/6214
naught101

Antworten:


154

Sie können plt.scatterein cArgument übergeben, mit dem Sie die Farben auswählen können. Der folgende Code definiert ein colorsWörterbuch, um Ihre Diamantfarben den Plotfarben zuzuordnen.

import matplotlib.pyplot as plt
import pandas as pd

carat = [5, 10, 20, 30, 5, 10, 20, 30, 5, 10, 20, 30]
price = [100, 100, 200, 200, 300, 300, 400, 400, 500, 500, 600, 600]
color =['D', 'D', 'D', 'E', 'E', 'E', 'F', 'F', 'F', 'G', 'G', 'G',]

df = pd.DataFrame(dict(carat=carat, price=price, color=color))

fig, ax = plt.subplots()

colors = {'D':'red', 'E':'blue', 'F':'green', 'G':'black'}

ax.scatter(df['carat'], df['price'], c=df['color'].apply(lambda x: colors[x]))

plt.show()

df['color'].apply(lambda x: colors[x]) Ordnet die Farben effektiv von "Diamant" bis "Plotten" zu.

(Verzeihen Sie mir, dass ich kein weiteres Beispielbild erstellt habe. Ich denke, 2 ist genug: P)

Mit seaborn

Sie können seaborneinen Wrapper verwenden matplotlib, der es standardmäßig hübscher aussehen lässt (eher meinungsbasiert, ich weiß: P), aber auch einige Plotfunktionen hinzufügt.

Hierfür können Sie seaborn.lmplotmit verwenden fit_reg=False(was verhindert, dass automatisch eine Regression durchgeführt wird).

Der folgende Code verwendet einen Beispieldatensatz. Durch Auswahl dieser hue='color'Option weisen Sie seaborn an, Ihren Datenrahmen anhand Ihrer Farben aufzuteilen und dann jeden einzelnen zu zeichnen.

import matplotlib.pyplot as plt
import seaborn as sns

import pandas as pd

carat = [5, 10, 20, 30, 5, 10, 20, 30, 5, 10, 20, 30]
price = [100, 100, 200, 200, 300, 300, 400, 400, 500, 500, 600, 600]
color =['D', 'D', 'D', 'E', 'E', 'E', 'F', 'F', 'F', 'G', 'G', 'G',]

df = pd.DataFrame(dict(carat=carat, price=price, color=color))

sns.lmplot('carat', 'price', data=df, hue='color', fit_reg=False)

plt.show()

Geben Sie hier die Bildbeschreibung ein

Ohne zu seabornbenutzenpandas.groupby

Wenn Sie Seaborn nicht verwenden möchten, können Sie pandas.groupbydie Farben allein verwenden und sie dann nur mit matplotlib zeichnen. Sie müssen jedoch die Farben manuell zuweisen. Ich habe unten ein Beispiel hinzugefügt:

fig, ax = plt.subplots()

colors = {'D':'red', 'E':'blue', 'F':'green', 'G':'black'}

grouped = df.groupby('color')
for key, group in grouped:
    group.plot(ax=ax, kind='scatter', x='carat', y='price', label=key, color=colors[key])

plt.show()

Dieser Code nimmt denselben DataFrame wie oben an und gruppiert ihn dann basierend auf color. Anschließend werden diese Gruppen durchlaufen und für jede Gruppe geplottet. Um eine Farbe auszuwählen, habe ich ein colorsWörterbuch erstellt, das die Diamantfarbe (zum Beispiel D) einer echten Farbe (zum Beispiel red) zuordnen kann .

Geben Sie hier die Bildbeschreibung ein


Danke, aber ich möchte nur herausfinden, wie man die Arbeit mit matplotlib alleine macht.
Avocado

Ja, über groupbykönnte ich das tun, also gibt es eine solche Funktion matplotlib, die automatisch für verschiedene Ebenen einer Kategorie mit unterschiedlichen Farben zeichnen kann, oder?
Avocado

@loganecolss Ok, ich verstehe :) Ich habe es erneut bearbeitet und ein sehr einfaches Beispiel hinzugefügt, das ein Wörterbuch verwendet, um die Farben zuzuordnen, ähnlich wie im groupbyBeispiel.
Ffisegydd

1
@Ffisegydd ax.scatterWie würden Sie mit der ersten Methode Legenden hinzufügen? Ich versuche zu verwenden label=df['color']und dann plt.legend()ohne Erfolg.
Ahoosh

1
Es wäre besser, ax.scatter(df['carat'], df['price'], c=df['color'].apply(lambda x: colors[x]))zuax.scatter(df['carat'], df['price'], c=df['color'].map(colors)
Dawei

33

Hier ist eine prägnante und generische Lösung für die Verwendung einer Farbpalette für Meeresbewohner.

Zuerst finden Sie eine Farbpalette Sie mögen und es optional visualisieren:

sns.palplot(sns.color_palette("Set2", 8))

Dann können Sie es matplotlibdamit verwenden:

# Unique category labels: 'D', 'F', 'G', ...
color_labels = df['color'].unique()

# List of RGB triplets
rgb_values = sns.color_palette("Set2", 8)

# Map label to RGB
color_map = dict(zip(color_labels, rgb_values))

# Finally use the mapped values
plt.scatter(df['carat'], df['price'], c=df['color'].map(color_map))

2
Ich mag deinen Ansatz. Im obigen Beispiel können Sie die Werte natürlich auch einfachen Farbnamen wie diesen zuordnen: 1) Definieren Sie die Farben Farben = {'D': 'Rot', 'E': 'Blau', 'F': 'Grün ',' G ':' schwarz '} 2) ordne sie so zu, wie du es getan hast: ax.scatter (df [' Karat '], df [' Preis '], c = df [' Farbe ']. Karte (Farben))
Stefan

1
Wie würden Sie in diesem Fall ein Etikett nach Farbe hinzufügen?
François Leblanc

2
Um mehr Abstraktion hinzuzufügen, können Sie das 8In sns.color_palette("Set2", 8)durch ersetzen len(color_labels).
Swier

Das ist großartig, sollte aber automatisch von Seegeborenen durchgeführt werden. Es ist unglaublich hinderlich, jedes Mal eine Karte für kategoriale Variablen verwenden zu müssen, wenn Sie schnell etwas zeichnen möchten . Ganz zu schweigen von der idiotischen Idee, Statistiken in der Handlung anzuzeigen. Seaborn lehnt leider aus diesen Gründen als Paket ab
Verfolgungsjagd

6

Mit Altair .

from altair import *
import pandas as pd

df = datasets.load_dataset('iris')
Chart(df).mark_point().encode(x='petalLength',y='sepalLength', color='species')

Geben Sie hier die Bildbeschreibung ein


Frage gestellt für matplotlib
Chuck

6

Ich hatte die gleiche Frage und habe den ganzen Tag damit verbracht, verschiedene Pakete auszuprobieren.

Ich hatte ursprünglich matlibplot verwendet: und war nicht zufrieden mit der Zuordnung von Kategorien zu vordefinierten Farben; oder Gruppieren / Aggregieren, dann Iterieren durch die Gruppen (und immer noch Farben zuordnen müssen). Ich hatte nur das Gefühl, dass es eine schlechte Paketimplementierung war.

Seaborn würde bei meinem Fall nicht funktionieren, und Altair funktioniert NUR in einem Jupyter-Notizbuch.

Die beste Lösung für mich war PlotNine, das "eine Implementierung einer Grammatik von Grafiken in Python ist und auf ggplot2 basiert".

Unten finden Sie den Plotnine-Code zum Replizieren Ihres R-Beispiels in Python:

from plotnine import *
from plotnine.data import diamonds

g = ggplot(diamonds, aes(x='carat', y='price', color='color')) + geom_point(stat='summary')
print(g)

Plotnine Diamanten Beispiel

So sauber und einfach :)


Frage gestellt für matplotlib
Chuck

5

Hier eine Kombination von Markern und Farben aus einer qualitativen Farbkarte in matplotlib:

import itertools
import numpy as np
from matplotlib import markers
import matplotlib.pyplot as plt

m_styles = markers.MarkerStyle.markers
N = 60
colormap = plt.cm.Dark2.colors  # Qualitative colormap
for i, (marker, color) in zip(range(N), itertools.product(m_styles, colormap)):
    plt.scatter(*np.random.random(2), color=color, marker=marker, label=i)
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0., ncol=4);

Geben Sie hier die Bildbeschreibung ein


In mpl.cm.Dark2.colors- mplscheint in Ihrem Code nicht definiert zu sein und Dark2hat kein Attribut colors.
Shovalt

@ Shovalt Danke für die Bewertung. Ich habe importiert haben , matplotlibwie mplich meinen Code korrigiert , indem Sie pltdas auch enthält cm. Zumindest in der matplotlibVersion, die ich verwende, hat 2.0.0 Dark2Attributcolors
Pablo Reyes

1
Spät, aber wenn Sie nicht das Farbattribut haben: iter (plt.cm.Dark2 (np.linspace (0,1, N)))
Geoff Lentsch

3

Mit df.plot ()

Normalerweise verwende ich beim schnellen Plotten eines DataFrame pd.DataFrame.plot(). Dies nimmt den Index als x-Wert, den Wert als y-Wert und zeichnet jede Spalte separat mit einer anderen Farbe. Ein DataFrame in dieser Form kann mit set_indexund erreicht werden unstack.

import matplotlib.pyplot as plt
import pandas as pd

carat = [5, 10, 20, 30, 5, 10, 20, 30, 5, 10, 20, 30]
price = [100, 100, 200, 200, 300, 300, 400, 400, 500, 500, 600, 600]
color =['D', 'D', 'D', 'E', 'E', 'E', 'F', 'F', 'F', 'G', 'G', 'G',]

df = pd.DataFrame(dict(carat=carat, price=price, color=color))

df.set_index(['color', 'carat']).unstack('color')['price'].plot(style='o')
plt.ylabel('price')

Handlung

Bei dieser Methode müssen Sie die Farben nicht manuell angeben.

Dieses Verfahren kann für andere Datenreihen sinnvoller sein. In meinem Fall habe ich Zeitreihendaten, daher besteht der MultiIndex aus Datum / Uhrzeit und Kategorien. Es ist auch möglich, diesen Ansatz für mehr als eine Spalte zum Färben zu verwenden, aber die Legende wird durcheinander gebracht.


0

Normalerweise mache ich das mit Seaborn, das auf Matplotlib aufgebaut ist

import seaborn as sns
iris = sns.load_dataset('iris')
sns.scatterplot(x='sepal_length', y='sepal_width',
              hue='species', data=iris); 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.