построить разные цвета для разных категорийных уровней, используя matplotlib

104

У меня есть этот фрейм данных, 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

авокадо
источник
1
Было бы действительно хорошо иметь что-то подобное, встроенное в matplotlib, но похоже, что это будет непросто. Обсуждение здесь: github.com/matplotlib/matplotlib/issues/6214
naught101 07

Ответы:

159

Вы можете передать 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.lmplotwith fit_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).

введите описание изображения здесь

Ffisegydd
источник
Спасибо, но я просто хочу узнать, как выполнять эту работу только с помощью matplotlib.
авокадо
Да, через groupbyя могу это сделать, так что есть такая функция, matplotlibкоторая может автоматически рисовать для разных уровней категории, используя разные цвета, верно?
авокадо
@loganecolss Хорошо, понятно :) Я снова отредактировал его и добавил очень простой пример, который использует словарь для сопоставления цветов, аналогично groupbyпримеру.
Ffisegydd 01
1
@Ffisegydd Используя первый метод ax.scatter, как бы вы добавили к нему легенды? Я пытаюсь использовать , label=df['color']а затем plt.legend()без успеха.
ahoosh 06
1
Лучше бы поменять 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)
Давэй
39

Вот краткое и универсальное решение для использования морской палитры.

Сначала найдите понравившуюся цветовую палитру и при желании визуализируйте ее:

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))
Ремс
источник
2
Мне нравится твой подход. Учитывая приведенный выше пример, вы, конечно, также можете сопоставить значения с простыми именами цветов, например: 1) определить цвета colors = {'D': 'красный', 'E': 'синий', 'F': 'зеленый ',' G ':' black '} 2) сопоставьте их так же, как и вы: ax.scatter (df [' carat '], df [' price '], c = df [' color ']. Map (colors))
Стефан
1
Но как бы вы добавили метку по цвету в этом случае?
François Leblanc
3
Чтобы добавить еще немного абстракции, вы можете заменить 8in sns.color_palette("Set2", 8)на len(color_labels).
Swier
Это здорово, но seaborn должна делать это автоматически. Необходимость использовать карту для категориальных переменных каждый раз, когда вы хотите что-то быстро построить, невероятно мешает. Не говоря уже об идиотской идее убрать возможность отображения статистики на сюжете. Сиборн, к сожалению, отказывается от посылки по этим причинам
погоня
7

У меня был тот же вопрос, и я весь день пробовал разные пакеты.

Изначально я использовал 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)

Пример плотнинных бриллиантов

Так чисто и просто :)

расправляться
источник
Вопрос задан для matplotlib
Чак
6

Используя Альтаир .

from altair import *
import pandas as pd

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

введите описание изображения здесь

Нипун Батра
источник
Вопрос задан для matplotlib
Чак
5

Вот сочетание маркеров и цветов из качественной палитры 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);

введите описание изображения здесь

Пабло Рейес
источник
In mpl.cm.Dark2.colors- mplпохоже, не определен в вашем коде и Dark2не имеет атрибута colors.
Шовальт
@Shovalt Спасибо за обзор. Я должен был импортировать matplotlibкак mpl, я исправил свой код, используя pltкоторый также содержит cm. По крайней мере, в matplotlibверсии, которую я использую 2.0.0 Dark2, есть атрибутcolors
Пабло Рейес,
1
Поздно, но если у вас нет атрибута цветов: iter (plt.cm.Dark2 (np.linspace (0,1, N)))
Джефф Ленч 06
3

С 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 и категорий. Также можно использовать этот подход для более чем одного столбца для раскрашивания, но легенда становится беспорядочной.

Саймон
источник
0

Обычно я использую Seaborn, который построен поверх matplotlib.

import seaborn as sns
iris = sns.load_dataset('iris')
sns.scatterplot(x='sepal_length', y='sepal_width',
              hue='species', data=iris); 
ВИКТОР РОДЕНЬО САНЧЕС
источник
0

Вы можете преобразовать категориальный столбец в числовой с помощью команд:

#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.
j6m8