Сюжет разного цвета для разных категориальных уровней с использованием matplotlib
У меня есть этот фрейм данных 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)
![enter image description here]()
Интересно, как это можно сделать в Python с помощью matplotlib
?
PS:
Я знаю о вспомогательных пакетах построения, таких как seaborn
и ggplot for python
, и я не предпочитаю их, просто хочу узнать, возможно ли выполнить задание, используя только matplotlib
;; P
Ответы
Ответ 1
Вы можете передать аргумент plt.scatter
a 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
с помощью fit_reg=False
(что предотвращает автоматическое выполнение некоторой регрессии).
В приведенном ниже коде используется примерный набор данных. Выбрав hue='color'
, вы скажете морскому дну разбить ваш фреймворк на основе ваших цветов, а затем нарисуйте каждый.
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]()
Без seaborn
с помощью pandas.groupby
Если вы не хотите использовать морское дно, вы можете использовать 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
).
![enter image description here]()
Ответ 2
Здесь представлено краткое и общее решение для использования палитра с морскими цветами.
Сначала найдите цветную палитру, которая вам нравится, и, возможно, визуализируйте ее:
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))
Ответ 3
Вот комбинация маркеров и цветов из качественной карты цветов в 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]()
Ответ 4
Используя Альтаир.
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
У меня был один и тот же вопрос, и я провел весь день, пробуя разные пакеты.
Первоначально я использовал matlibplot: и не был доволен ни отображением категорий в предопределенных цветах; или группирование/агрегирование, затем итерация по группам (и все же необходимость сопоставления цветов). Я просто чувствовал, что это плохая реализация пакета.
Seaborn не будет работать над моим делом, и Altair работает ТОЛЬКО в ноутбуке Jupyter.
Лучшим решением для меня был PlotNine, "который представляет собой реализацию грамматики графики в Python и основанную на ggplot2".
Ниже приведен код plotnine для репликации вашего примера 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)
![plotnine diamonds example]()
Так чисто и просто :)
Ответ 6
Я обычно делаю это, используя Seaborn, который построен поверх matplotlib
import seaborn as sns
iris = sns.load_dataset('iris')
sns.scatterplot(x='sepal_length', y='sepal_width',
hue='species', data=iris);
Ответ 7
С помощью 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')
![plot]()
С помощью этого метода вам не нужно вручную указывать цвета.
Эта процедура может иметь больше смысла для других рядов данных. В моем случае у меня есть данные временных рядов, поэтому MultiIndex состоит из datetime и категорий. Также возможно использовать этот подход для более чем одного столбца, но легенда становится беспорядочной.