如何向 seaborn FacetGrid 添加额外的绘图并指定颜色

How to add additional plots to a seaborn FacetGrid and specify colors

有没有办法创建一个 Seaborn 线图,所有的线都是灰色的,平均值是红色的?我正在尝试使用 relplot 来执行此操作,但我不知道如何将平均值与数据分开(而且似乎未绘制平均值?)。

制作可重现的数据框

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']
                 )

密谋尝试

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
)

  • 这取决于想要的结果。 seaborn.relplot 文档有一个 fmri 数据集的示例,它仅显示 meanci,因此结果取决于您如何设置 hueevent 个参数。
  • 要为所有线条指定单一颜色,请使用 units 而不是 huestyle(如 mwaskom 所指出的),然后设置 color='grey'.
  • 对于本OP的要求,接受的答案是最好的选择。但是,在需要从不是用于创建 relplotdata 的来源添加数据的情况下,此解决方案可能更合适,因为它允许访问每个 axes图,并从 不同 数据源添加 something
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')

资源

  • 另请参阅以下答案,了解将信息添加到 seaborn FacetGrid 的其他方法

我想你想在 relplot 的调用中使用 units,然后使用 map:

添加一层 lineplot
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)

我从 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? 来到这里,post 不能到那里。

但我发现最简单的解决方案是简单地将 hue_orderpalette 参数传递给 relplot 调用。见下文:

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()

这与接受的答案有点不同。但同样,我是从另一个已关闭的问题来到这里的。这也不使用任何 for 循环,应该更直接。

输出: