简体   繁体   English

如何向 seaborn FacetGrid 添加附加图并指定 colors

[英]How to add additional plots to a seaborn FacetGrid and specify colors

Is there a way to create a Seaborn line plot with all the lines gray and the mean as a red line?有没有办法创建一条 Seaborn 线 plot ,所有线均为灰色,平均值为红线? I'm trying to do this with relplot but I don't know how to separate the mean from the data (and it appears the mean isn't being plotted?).我正在尝试使用relplot来做到这一点,但我不知道如何将平均值与数据分开(而且似乎平均值没有被绘制?)。

Make reproducible data frame制作可重现的数据框

np.random.seed(1)
n1 = 100
n2 = 10
idx = np.arange(0,n1*2)
x, y, cat, id2 = [], [], [], []

x1 = list(np.random.uniform(-10,10,n2))
for i in idx: 
    x.extend(x1)
    y.extend(list(np.random.normal(loc=0, scale=0.5, size=n2)))
    cat.extend(['A', 'B'][i > n1])
    id2.append(idx[i])

id2 = id2 * n2
id2.sort()
df1 = pd.DataFrame(list(zip(id2, x, y, cat)), 
                  columns =['id2', 'x', 'y', 'cat']
                 )

Plotting attempt绘图尝试

g = sns.relplot(
    data=df1, x='x', y='y', hue='id2',
    col='cat', kind='line',
    palette='Greys',
    facet_kws=dict(sharey=False, 
                   sharex=False
                  ),
    legend=False
)

在此处输入图像描述

I think you want units in the call to relplot and then add a layer of lineplot using map :我认为您希望调用relplot中的units ,然后使用lineplot添加一层线map

import seaborn as sns
import pandas as pd

fm = sns.load_dataset('fmri').query("event == 'stim'")
g = sns.relplot(
    data=fm, kind='line',
    col='region', x='timepoint', y='signal', units='subject',
    estimator=None, color='.7'
)
g.data = fm  # Hack needed to work around bug on v0.11, fixed in v0.12.dev
g.map(sns.lineplot, 'timepoint', 'signal', color='r', ci=None, lw=3)

在此处输入图像描述

  • It depends on the desired result.这取决于期望的结果。 Theseaborn.relplot documentation has an example for the fmri dataset that only shows the mean and the ci , so the result depends on how you set the hue and event parameters. seaborn.relplot文档有一个fmri数据集的示例,该示例仅显示meanci ,因此结果取决于您如何设置hueevent参数。
  • To specify a single color for all the lines, use units instead of hue or style (as pointed out by mwaskom ), and then set color='grey' .要为所有线条指定单一颜色,请使用units而不是huestyle (如mwaskom所指出的那样),然后设置color='grey'
  • For the requirements of this OP, the accepted answer is the best option.对于此 OP 的要求,接受的答案是最佳选择。 However, in cases which require adding data from a source that isn't the data used to create the relplot , this solution may be more appropriate, as it allows for accessing each axes of the figure, and adding something from a different data source.但是,在需要从不是用于创建relplotdata的源中添加数据的情况下,此解决方案可能更合适,因为它允许访问图形的每个axes ,并添加来自不同数据源的内容
import seaborn as sns
import pandas as pd

# load and select data only where event is stim
fm = sns.load_dataset('fmri').query("event == 'stim'")

# groupby to get the mean for each region by timepoint
fmg = fm.groupby(['region', 'timepoint'], as_index=False).signal.mean()

# plot the fm dataframe
g = sns.relplot(data=fm, col='region', x='timepoint', y='signal',
                units='subject', kind='line', ci=None, color='grey', estimator=None)

# extract and flatten the axes from the figure
axes = g.axes.flatten()

# iterate through each axes
for ax in axes:
    # extract the region
    reg = ax.get_title().split(' = ')[1]
    
    # select the data for the region
    data = fmg[fmg.region.eq(reg)]
    
    # plot the mean line
    sns.lineplot(data=data, x='timepoint', y='signal', ax=ax, color='red', label='mean', lw=3)
    
# fix the legends
axes[0].legend().remove()
axes[1].legend(title='Subjects', bbox_to_anchor=(1, 1), loc='upper left')

在此处输入图像描述

Resources资源

I came here from Seaborn's relplot: Is there a way to assign a specific color to all lines and another color to another single line when using the hue argument?我是从Seaborn 的 relplot 来到这里的:有没有办法在使用 hue 参数时为所有线条分配一种特定的颜色,并为另一条线分配另一种颜色? and can't post there.并且不能在那里发帖。

But I find the simplest solution is to simply pass a hue_order as well as a palette argument to the relplot call.但我发现最简单的解决方案是简单地将一个hue_order和一个palette参数传递给relplot调用。 See below:见下文:

import seaborn as sbn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt


sim = ['a'] * 100 + ['b'] * 100 + ['c'] * 100
var = (['u'] * 50 + ['v'] * 50)*3

x = np.linspace(0, 50, 50)
x = np.hstack([x]*6)

y = np.random.rand(300)

df = pd.DataFrame({'x':x, 'y':y, 'sim':sim, 'var':var})

hueOrder = ["a", "b", "c"] # Specifies the order for the palette
hueColor = ["r", "r", "b"] # Specifies the colors for the hueOrder (just make two the same color, and one different)

sbn.relplot(data=df, x='x', y='y', kind='line', col='var', hue='sim', hue_order=hueOrder, palette=hueColor)
plt.show()

This is a bit different then the accepted answer.这与接受的答案有点不同。 But again, I came here from another question that is closed.但是,我再次从另一个已关闭的问题来到这里。 This also doesn't use any for loops and should be more straight forward.这也不使用任何 for 循环,应该更直接。

Output: Output: 在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM