У меня есть этот фрейм данных, diamonds
который состоит из таких переменных, как (carat, price, color)
, и я хочу нарисовать диаграмму рассеяния от price
до carat
для каждой color
, что означает, что разные color
имеют разные цвета на графике.
Это легко сделать R
с 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)
Интересно, как это можно сделать в Python с помощью matplotlib
?
PS:
Я знаю о вспомогательных пакетах построения графиков, таких как seaborn
и ggplot for python
, и я не предпочитаю их, просто хочу узнать, можно ли выполнить эту работу, используя в matplotlib
одиночку,; P
matplotlib
pandas
visualization
авокадо
источник
источник
Ответы:
Вы можете передать
plt.scatter
вc
аргумент , который позволит вам выбрать цвета. В приведенном ниже коде определяетсяcolors
словарь для сопоставления цветов ромба с цветами печати.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])
эффективно отображает цвета от «ромба» до «черчения».(Простите меня за то, что я не поместил еще один пример изображения, я думаю, что 2 достаточно: P)
С участием
seaborn
Вы можете использовать
seaborn
обертку,matplotlib
которая делает его красивее по умолчанию (скорее, на основе мнения, я знаю: P), но также добавляет некоторые функции построения графиков.Для этого вы можете использовать
seaborn.lmplot
withfit_reg=False
(что предотвращает автоматическое выполнение некоторой регрессии).В приведенном ниже коде используется пример набора данных. Выбирая,
hue='color'
вы говорите seaborn разделить фрейм данных на основе ваших цветов, а затем построить каждый из них.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
использованияpandas.groupby
Если вы не хотите использовать seaborn, вы можете использовать
pandas.groupby
только цвета, а затем построить их, используя только matplotlib, но вам придется вручную назначать цвета по ходу работы, я добавил пример ниже: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()
Этот код предполагает тот же DataFrame, что и выше, а затем группирует его на основе
color
. Затем он перебирает эти группы, составляя график для каждой из них. Чтобы выбрать цвет, я создалcolors
словарь, который может сопоставить цвет алмаза (напримерD
) с реальным цветом (напримерred
).источник
groupby
я могу это сделать, так что есть такая функция,matplotlib
которая может автоматически рисовать для разных уровней категории, используя разные цвета, верно?groupby
примеру.ax.scatter
, как бы вы добавили к нему легенды? Я пытаюсь использовать ,label=df['color']
а затемplt.legend()
без успеха.ax.scatter(df['carat'], df['price'], c=df['color'].apply(lambda x: colors[x]))
наax.scatter(df['carat'], df['price'], c=df['color'].map(colors)
Вот краткое и универсальное решение для использования морской палитры.
Сначала найдите понравившуюся цветовую палитру и при желании визуализируйте ее:
sns.palplot(sns.color_palette("Set2", 8))
Затем вы можете использовать его для
matplotlib
этого:# 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))
источник
8
insns.color_palette("Set2", 8)
наlen(color_labels)
.У меня был тот же вопрос, и я весь день пробовал разные пакеты.
Изначально я использовал matlibplot: и меня не устраивало сопоставление категорий с предопределенными цветами; или группировка / агрегация, а затем итерация по группам (и при этом все еще нужно отображать цвета). Я просто почувствовал, что это плохая реализация пакета.
Сиборн не работал бы в моем случае, а Альтаир работает ТОЛЬКО внутри Jupyter Notebook.
Лучшим решением для меня был PlotNine, который «представляет собой реализацию грамматики графики на Python, основанную на ggplot2».
Ниже приведен программный код для воспроизведения вашего примера R в 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)
Так чисто и просто :)
источник
Используя Альтаир .
from altair import * import pandas as pd df = datasets.load_dataset('iris') Chart(df).mark_point().encode(x='petalLength',y='sepalLength', color='species')
источник
Вот сочетание маркеров и цветов из качественной палитры
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);
источник
mpl.cm.Dark2.colors
-mpl
похоже, не определен в вашем коде иDark2
не имеет атрибутаcolors
.matplotlib
какmpl
, я исправил свой код, используяplt
который также содержитcm
. По крайней мере, вmatplotlib
версии, которую я использую 2.0.0Dark2
, есть атрибутcolors
С df.plot ()
Обычно при быстром построении DataFrame я использую
pd.DataFrame.plot()
. Он принимает индекс как значение x, значение как значение y и отображает каждый столбец отдельно с другим цветом. DataFrame в этой форме может быть получен с помощьюset_index
и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')
При использовании этого метода вам не нужно вручную указывать цвета.
Эта процедура может иметь больше смысла для других рядов данных. В моем случае у меня есть данные таймсерий, поэтому MultiIndex состоит из datetime и категорий. Также можно использовать этот подход для более чем одного столбца для раскрашивания, но легенда становится беспорядочной.
источник
Обычно я использую Seaborn, который построен поверх matplotlib.
import seaborn as sns iris = sns.load_dataset('iris') sns.scatterplot(x='sepal_length', y='sepal_width', hue='species', data=iris);
источник
Вы можете преобразовать категориальный столбец в числовой с помощью команд:
#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)
источник
astype('category')
, а неcategorical
.