Изменение цвета и маркера каждой точки с использованием морского графика

У меня есть этот код, слегка измененный из здесь:

import seaborn as sns
sns.set(style="darkgrid")

tips = sns.load_dataset("tips")
color = sns.color_palette()[5]
g = sns.jointplot("total_bill", "tip", data=tips, kind="reg", stat_func=None,
                  xlim=(0, 60), ylim=(0, 12), color='k', size=7)

g.set_axis_labels('total bill', 'tip', fontsize=16)

и я получаю красивый сюжет. Однако в моем случае мне нужно иметь возможность изменить цвет и формат каждой отдельной точки.

Я пытался использовать ключевые слова marker, style и fmt, но получаю сообщение об ошибке TypeError: jointplot() got an unexpected keyword argument.

Каков правильный способ сделать это? Я бы хотел избежать вызова sns.JointGrid и ручного построения данных и предельных распределений.


person pbreach    schedule 18.11.2014    source источник
comment
Может быть, я неправильно понимаю, но согласно этому ответу, вы не можете передать список маркеров в plt.scatter, поэтому оболочка seaborn тоже не будет работать.   -  person cd98    schedule 19.11.2014
comment
Стрелять. Я должен буду отредактировать это. Может быть, можно было бы очистить точки после создания фигуры и нанести каждую по отдельности.   -  person pbreach    schedule 19.11.2014
comment
В итоге получилось не так уж и сложно. Все, что мне нужно было сделать, это g.ax_joint.cla() очистить оси, на которых нанесены точки, а затем нанести точки, используя ответ, который вы упомянули. Регрессия ушла, но мне в любом случае не нужна эта часть, только точки с маргинальными распределениями.   -  person pbreach    schedule 19.11.2014
comment
Не могли бы вы ответить на свой вопрос, показав свой код (а затем принять его)? Еще лучше, если вы можете добавить изображение, чтобы люди в будущем могли использовать его в качестве ссылки :)   -  person cd98    schedule 19.11.2014


Ответы (6)


Решение этой задачи почти ничем не отличается от решения из matplotlib (построение точечной диаграммы с разными маркерами и цветами), за исключением того, что я хотел сохранить маргинальные распределения:

import seaborn as sns
from itertools import product
sns.set(style="darkgrid")

tips = sns.load_dataset("tips")
color = sns.color_palette()[5]
g = sns.jointplot("total_bill", "tip", data=tips, kind="reg", stat_func=None,
                  xlim=(0, 60), ylim=(0, 12), color='k', size=7)

#Clear the axes containing the scatter plot
g.ax_joint.cla()

#Generate some colors and markers
colors = np.random.random((len(tips),3))
markers = ['x','o','v','^','<']*100

#Plot each individual point separately
for i,row in enumerate(tips.values):
    g.ax_joint.plot(row[0], row[1], color=colors[i], marker=markers[i])

g.set_axis_labels('total bill', 'tip', fontsize=16)

Что дает мне это:

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

Линии регрессии больше нет, но это все, что мне было нужно.

person pbreach    schedule 19.11.2014
comment
plt.scatter не имеет никакого способа управлять маркером, используемым для отдельных точек, поэтому что-то вроде этого, вероятно, ваш лучший выбор, но вы можете сделать g.ax_joint.collections[0].set_visible(False) вместо очистки всех осей, что сохранит линию регрессии. - person mwaskom; 19.11.2014
comment
Как ни странно, это работало только при указании маркера. Без этого он не будет строить точки! - person Aku; 22.06.2018
comment
Откуда вы узнали, что доступны ['x','o','v','^','<'] стили маркеров? Мне трудно ориентироваться в документации Seaborn. (EDIT: я думаю, что нашел это ???? здесь ) - person dumbledad; 09.08.2019

Принятый ответ слишком сложен. plt.sca() можно использовать для этого более простым способом:

import matplotlib.pyplot as plt
import seaborn as sns

tips = sns.load_dataset("tips")
g = sns.jointplot("total_bill", "tip", data=tips, kind="reg", stat_func=None,
                  xlim=(0, 60), ylim=(0, 12))


g.ax_joint.cla() # or g.ax_joint.collections[0].set_visible(False), as per mwaskom's comment

# set the current axis to be the joint plot's axis
plt.sca(g.ax_joint)

# plt.scatter takes a 'c' keyword for color
# you can also pass an array of floats and use the 'cmap' keyword to
# convert them into a colormap
plt.scatter(tips.total_bill, tips.tip, c=np.random.random((len(tips), 3)))
person Max Shron    schedule 14.10.2015
comment
Я рекомендую пропустить вызов plt.sca и использовать объект осей напрямую: g.ax_joint.scatter(tips.total_bill, ...). По возможности избегайте конечного автомата pyplot. - person Paul H; 14.10.2015

Вы также можете указать его напрямую в списке аргументов благодаря ключевому слову: joint_kws (проверено с Seaborn 0.8.1). При необходимости вы также можете изменить свойства маргинала с помощью marginal_kws

Итак, ваш код становится:

import seaborn as sns
colors = np.random.random((len(tips),3))
markers = (['x','o','v','^','<']*100)[:len(tips)]

sns.jointplot("total_bill", "tip", data=tips, kind="reg",
    joint_kws={"color":colors, "marker":markers})
person Vincent Jeanselme    schedule 22.03.2018

  1. В seaborn/categorical.py найдите def swarmplot.
  2. Добавить параметр marker='o' перед **kwargs
  3. В kwargs.update добавьте marker=marker.

Затем добавьте, например. marker='x' в качестве параметра при построении графика с помощью sns.swarmplot(), как если бы вы использовали Matplotlib plt.scatter().

Просто столкнулся с такой же необходимостью, и иметь marker как kwarg не получилось. Итак, я бегло посмотрел. Мы можем установить другие параметры аналогичным образом. https://github.com/ccneko/seaborn/blob/master/seaborn/categorical.py

Здесь нужно лишь небольшое изменение, но вот разветвленная страница GitHub для быстрого ознакомления;)

person Claire    schedule 26.11.2017

Другой вариант — использовать JointGrid, так как JointPlot — это оболочка, упрощающая его использование.

import matplotlib.pyplot as plt
import seaborn as sns

tips = sns.load_dataset("tips")

g = sns.JointGrid("total_bill", "tip", data=tips)
g = g.plot_joint(plt.scatter, c=np.random.random((len(tips), 3)))
g = g.plot_marginals(sns.distplot, kde=True, color="k")
person Vlamir    schedule 08.09.2017

Два других ответа — сложные экстравагантности (на самом деле, они исходят от людей, которые действительно понимают, что происходит под капотом).

Вот ответ того, кто просто догадывается. Однако это работает!

tips = sns.load_dataset("tips")
g = sns.jointplot("total_bill", "tip", data=tips,
              c=tips.day.cat.codes, cmap='Set1', stat_func=None,
              xlim=(0, 60), ylim=(0, 12))
person riri    schedule 19.04.2016
comment
Я не думаю, что это работает; Я только что попробовал это в Seaborn 0.7.1 и получил ValueError: Supply a 'c' kwarg or a 'color' kwarg but not both; they differ but their functionalities overlap. Как бы хорошо это ни было, если бы аргумент c мог быть коллекцией, я не думаю, что это возможно. - person Nelson; 18.09.2016