web-dev-qa-db-fra.com

tracer des couleurs différentes pour différents niveaux qualitatifs à l'aide de matplotlib

J'ai cette trame de données diamonds qui est composée de variables comme (carat, price, color), et je veux tracer un diagramme de dispersion de price à carat pour chaque color, ce qui signifie différent color a une couleur différente dans le tracé.

Ceci est facile dans R avec 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)

enter image description here

Je me demande comment cela pourrait être fait dans Python en utilisant matplotlib?

PS:

Je connais des paquets de traçage auxiliaires, tels que seaborn et ggplot for python, et je ne les préfère pas, je veux juste savoir s'il est possible de faire le travail en utilisant matplotlib seul,; P

71
avocado

Vous pouvez passer _plt.scatter_ un argument c qui vous permettra de sélectionner les couleurs. Le code ci-dessous définit un dictionnaire colors pour mapper vos couleurs de diamant sur les couleurs de traçage.

_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]) associe efficacement les couleurs de "diamant" à "traçage".

(Pardonnez-moi de ne pas mettre un autre exemple d'image, je pense que 2 est suffisant: P)

Avec seaborn

Vous pouvez utiliser seaborn qui enveloppe matplotlib pour le rendre plus joli par défaut (plutôt basé sur l'opinion, je sais: P), mais ajoute également quelques fonctions de traçage.

Pour cela, vous pouvez utiliser seaborn.lmplot avec _fit_reg=False_ (ce qui l’empêche de procéder automatiquement à une régression).

Le code ci-dessous utilise un exemple de jeu de données. En sélectionnant _hue='color'_, vous indiquez à Seaborn de scinder votre base de données en fonction de vos couleurs, puis de tracer chacune d'elles.

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

enter image description here

Sans seaborn avec _pandas.groupby_

Si vous ne voulez pas utiliser Seaborn, vous pouvez utiliser _pandas.groupby_ pour obtenir les couleurs seules, puis les tracer en utilisant simplement matplotlib, mais vous devrez attribuer manuellement les couleurs au fur et à mesure, j'ai ajouté un exemple. au dessous de:

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

Ce code suppose le même DataFrame que ci-dessus, puis le groupe en fonction de color. Il parcourt ensuite ces groupes, en traçant pour chacun d'eux. Pour sélectionner une couleur, j'ai créé un dictionnaire colors qui peut mapper la couleur du diamant (par exemple D) sur une couleur réelle (par exemple red).

enter image description here

125
Ffisegydd

Voici une solution succincte et générique pour utiliser une palette de couleurs Seaborn.

D'abord trouvez une palette de couleurs vous aimez et visualisez-le éventuellement:

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

Ensuite, vous pouvez l'utiliser avec matplotlib pour ce faire:

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

Voici une combinaison de marqueurs et de couleurs tirés d’une palette de couleurs qualitative dans 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);

enter image description here

5
Pablo Reyes

Utilisation de Altair .

from altair import *
import pandas as pd

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

enter image description here

5
Nipun Batra

J'avais la même question et j'ai passé toute la journée à essayer différents packages.

J'avais initialement utilisé matlibplot: et je n'étais pas satisfait de la correspondance des catégories avec des couleurs prédéfinies; ou regroupement/agrégation puis itération à travers les groupes (tout en ayant à cartographier les couleurs). J'ai juste senti que c'était une mauvaise mise en œuvre du paquet.

Seaborn ne fonctionnerait pas avec mon cas et Altair ne travaille UNIQUEMENT qu’à l’intérieur d’un cahier Jupyter.

La meilleure solution pour moi était PlotNine, qui "est une implémentation d’une grammaire graphique en Python et basée sur ggplot2".

Voici le code plotnine pour répliquer votre exemple R en 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 diamonds example

Si propre et simple :)

4
deprekate

Je le fais habituellement en utilisant Seaborn qui est construit sur matplotlib

import seaborn as sns
iris = sns.load_dataset('iris')
sns.scatterplot(x='sepal_length', y='sepal_width',
              hue='species', data=iris); 
0

Avec df.plot ()

Normalement, lorsque je trace rapidement un DataFrame, j'utilise pd.DataFrame.plot(). Cela prend l'index comme valeur x, la valeur comme la valeur y et trace chaque colonne séparément avec une couleur différente. Un DataFrame sous cette forme peut être obtenu en utilisant set_index et 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')

plot

Avec cette méthode, il n'est pas nécessaire de spécifier manuellement les couleurs.

Cette procédure peut avoir plus de sens pour d'autres séries de données. Dans mon cas, j'ai des données temporelles, donc le MultiIndex est constitué de date/heure et de catégories. Il est également possible d'utiliser cette approche pour plus d'une colonne à colorier, mais la légende est en train de se gâter.

0
Simon