Muszę tej ramki danych diamonds
, które składa się ze zmiennych jak (carat, price, color)
, i chce wyciągnąć wykres punktowy price
, aby carat
dla każdego color
, który oznacza różne color
ma inny kolor w powierzchni.
Jest to łatwe R
dzięki 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)
Zastanawiam się, jak można to zrobić w Pythonie za pomocą matplotlib
?
PS:
Wiem o pomocniczych pakietach do kreślenia, takich jak seaborn
i ggplot for python
, i nie lubię ich, chcę się tylko dowiedzieć, czy da się to zrobić matplotlib
samodzielnie,; P
matplotlib
pandas
visualization
awokado
źródło
źródło
Odpowiedzi:
Możesz przejść
plt.scatter
doc
argumentu, który pozwoli Ci wybrać kolory. Poniższy kod definiujecolors
słownik do mapowania kolorów diamentów na kolory kreślenia.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])
efektywnie odwzorowuje kolory od „diamentu” do „kreślenia”.(Wybaczcie, że nie umieszczam kolejnego przykładowego obrazu, myślę, że 2 wystarczy: P)
Z
seaborn
Możesz użyć,
seaborn
która jest otoką,matplotlib
która sprawia, że domyślnie wygląda ładniej (raczej oparta na opiniach, wiem: P), ale także dodaje kilka funkcji kreślących.Do tego możesz użyć
seaborn.lmplot
withfit_reg=False
(co zapobiega automatycznemu wykonywaniu regresji).Poniższy kod wykorzystuje przykładowy zestaw danych. Wybierając
hue='color'
, każesz seabornowi podzielić ramkę danych na podstawie twoich kolorów, a następnie wykreślić każdy z nich.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()
Bez
seaborn
użyciapandas.groupby
Jeśli nie chcesz używać poroża morskiego, możesz użyć,
pandas.groupby
aby uzyskać same kolory, a następnie wykreślić je za pomocą tylko matplotlib, ale będziesz musiał ręcznie przypisywać kolory w trakcie, dodałem przykład poniżej: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()
Ten kod zakłada tę samą ramkę DataFrame, co powyżej, a następnie grupuje ją na podstawie
color
. Następnie dokonuje iteracji po tych grupach, wykreślając dla każdej z nich. Aby wybrać kolor, stworzyłemcolors
słownik, który może odwzorować kolor diamentu (na przykładD
) na rzeczywisty kolor (na przykładred
).źródło
groupby
to mogłem to zrobić, więc jest taka funkcja,matplotlib
która może automatycznie rysować dla różnych poziomów kategorii przy użyciu innego koloru, prawda?groupby
przykładzie.ax.scatter
, jak dodać do niej legendy? Próbuję użyć,label=df['color']
aleplt.legend()
bezskutecznie.ax.scatter(df['carat'], df['price'], c=df['color'].apply(lambda x: colors[x]))
naax.scatter(df['carat'], df['price'], c=df['color'].map(colors)
Oto zwięzłe i ogólne rozwiązanie dotyczące korzystania z palety kolorów morskiej.
Najpierw znajdź paletę kolorów, którą lubisz i opcjonalnie zwizualizuj ją:
sns.palplot(sns.color_palette("Set2", 8))
Następnie możesz go użyć,
matplotlib
robiąc to:# 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))
źródło
8
insns.color_palette("Set2", 8)
przezlen(color_labels)
.Miałem to samo pytanie i spędziłem cały dzień na wypróbowywaniu różnych pakietów.
Pierwotnie użyłem matlibplot: i nie byłem zadowolony z przypisania kategorii do predefiniowanych kolorów; lub grupowanie / agregowanie, a następnie iterowanie po grupach (i wciąż konieczność mapowania kolorów). Po prostu czułem, że to słaba implementacja pakietu.
Seaborn nie działałby na mojej walizce, a Altair działa TYLKO w notatniku Jupyter.
Najlepszym dla mnie rozwiązaniem był PlotNine, który „jest implementacją gramatyki grafiki w Pythonie i opartą na ggplot2”.
Poniżej znajduje się kod plotnine do replikacji przykładu R w Pythonie:
from plotnine import * from plotnine.data import diamonds g = ggplot(diamonds, aes(x='carat', y='price', color='color')) + geom_point(stat='summary') print(g)
Tak czysto i prosto :)
źródło
Korzystanie z Altair .
from altair import * import pandas as pd df = datasets.load_dataset('iris') Chart(df).mark_point().encode(x='petalLength',y='sepalLength', color='species')
źródło
Tutaj kombinacja markerów i kolorów z jakościowej mapy kolorów w
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);
źródło
mpl.cm.Dark2.colors
-mpl
nie wydaje się być zdefiniowane w kodzie iDark2
nie ma atrybutucolors
.matplotlib
jakompl
, poprawiłem swój kod za pomocą,plt
który również zawieracm
. Przynajmniej wmatplotlib
wersji, której używam 2.0.0Dark2
, ma atrybutcolors
Z df.plot ()
Zwykle podczas szybkiego kreślenia ramki DataFrame używam
pd.DataFrame.plot()
. To przyjmuje indeks jako wartość x, wartość jako wartość y i wykreśla każdą kolumnę osobno innym kolorem. Ramkę DataFrame w tym formularzu można uzyskać za pomocąset_index
iunstack
.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')
Dzięki tej metodzie nie musisz ręcznie określać kolorów.
Ta procedura może mieć większy sens w przypadku innych serii danych. W moim przypadku mam dane timeeries, więc MultiIndex składa się z datetime i kategorii. Możliwe jest również użycie tego podejścia do kolorowania więcej niż jednej kolumny, ale legenda robi się bałagan.
źródło
Zwykle robię to za pomocą Seaborn, który jest zbudowany na bazie matplotlib
import seaborn as sns iris = sns.load_dataset('iris') sns.scatterplot(x='sepal_length', y='sepal_width', hue='species', data=iris);
źródło
Możesz przekonwertować kolumnę kategorialną na liczbową, używając poleceń:
#we converting it into categorical data cat_col = df['column_name'].astype('categorical') #we are getting codes for it cat_col = cat_col.cat.codes # we are using c parameter to change the color. plt.scatter(df['column1'],df['column2'], c=cat_col)
źródło