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)
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
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)
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()
_
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
).
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))
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);
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')
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)
Si propre et simple :)
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);
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')
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.