使用 Seaborn 在散点图上绘制线条

Drawing lines on scatter with Seaborn

我的 objective 是在使用 seaborn 绘制的图上的 y = 0 上绘制一条水平红线:sns.lmplotcol=row= 拆分。

import numpy as np, seaborn as sns, pandas as pd
np.random.seed(5)

myData = pd.DataFrame({'x' :  np.arange(1, 101), 'y': np.random.normal(0, 4, 100),\
'z' : ['a','b']*50, 'w':np.random.poisson(0.15,100)})


sns.lmplot("x", "y", col="z", row="w", data=myData, fit_reg=False)
plt.plot(np.linspace(-20,120,1000), [0]*1000, 'r-')

我们可以看到只有最后一个图,在图的数组中,用红线标记:

感谢您的帮助,

编辑: 改写了问题以说明我们使用 col= and/or row= 生成图表数组的情况,我们希望在每个地块上追踪线条。

Seaborn 实际上只是 matplotlib 的一个接口,因此您也可以使用所有标准的 matplotlib 函数。在你的 seaborn 绘图对我有用后导入 pyplot 并绘制一条红色水平线。

import numpy as np, seaborn as sns, pandas as pd
import matplotlib.pyplt as plt
np.random.seed(5)

myData = pd.DataFrame({'x' :  np.arange(1, 101), 'y': np.random.normal(0, 4, 100)})

sns.lmplot("x", "y", data=myData, line_kws={'xdata': '0,1','ydata': '0,0','color': 'k', 'linestyle':'-', 'linewidth':'5'}, fit_reg=False)
plt.plot(np.linspace(-20,120,1000), [0]*1000, 'r')

我的头像在这里 - http://i.imgur.com/J7Lvt52.png

因此这段代码适用于我们使用 col=row=hue=.

的一般情况
import numpy as np, seaborn as sns, pandas as pd
np.random.seed(5)

myData = pd.DataFrame({'x' :  np.arange(1, 101), 'y': np.random.normal(0, 4, 100),\
'z' : ['a','b']*50, 'w':np.random.poisson(0.15,100), 'hueMe':['q','w','e','r','t']*20})

myPlot = sns.FacetGrid(col="z", row='w', hue='hueMe', data=myData, size=5)
myPlot = myPlot.map(plt.scatter, "x", "y").set(xlim=(-20,120) , ylim=(-15,15))
myPlot = myPlot.map_dataframe(plt.plot, [-20,120], [0,0], 'r-').add_legend().set_axis_labels("x", "y")
plt.show()

不确定为什么水平线的颜色是每个单独图上使用的最后一种颜色,但我暂时放弃了:)

自从我在寻找答案时遇到这个问题,这里是我最终发现的一个更通用的答案:

map_dataframe 还将接受用户定义的函数(并将数据框传递给此函数),该函数非常强大,因为您可以在 facetgrid 上绘制任何内容。在 OP 案例中:

def plot_hline(y,**kwargs):
    data = kwargs.pop("data") #get the data frame from the kwargs
    plt.axhline(y=y, c='red',linestyle='dashed',zorder=-1) #zorder places the line underneath the other points

myPlot = sns.FacetGrid(col="z", row='w', hue='hueMe', data=myData, size=5)
myPlot.map(plt.scatter, "x", "y").set(xlim=(-20,120) , ylim=(-15,15))
myPlot.map_dataframe(plot_hline,y=0)
plt.show()

我的问题稍微复杂一些,因为我想在每个面都有不同的水平线。

为了复制我的案例,假设 'z' 变量有两个样本(a 和 b),每个样本都有一个观测值 'obs'(我已将其添加到下面的 myData 中)。 'hueMe' 表示每个样本的建模值。

myData = pd.DataFrame({'x' :  np.arange(1, 101), 
                       'y': np.random.normal(0, 4, 100),
                       'z' : ['a','b']*50,
                       'w':np.random.poisson(0.15,100),
                       'hueMe':['q','w','e','r','t']*20,
                       'obs':[3,2]*50})

当您将数据框传递给plot_hline时,您需要为每个'z'样本删除'obs'的重复值,因为axhline只能为[=取一个值15=]。 (请记住,在我们的例子中,每个样本都有 1 个观察值 'obs',但有多个建模值 'hueMe')。此外,y 必须是标量(而不是系列),因此您需要索引数据框以提取值本身。

def plot_hline(y,z, **kwargs):
    data = kwargs.pop("data") #the data passed in through kwargs is a subset of the original data - only the subset for the row and col being plotted. it's a for loop in disguise.
    data = data.drop_duplicates([z]) #drop the duplicate rows
    yval = data[y].iloc[0] #extract the value for your hline.
    plt.axhline(y=yval, c='red',linestyle='dashed',zorder=-1)


myPlot = sns.FacetGrid(col="z", row='w', hue='hueMe', data=myData, size=5)
myPlot.map(plt.scatter, "x", "y").set(xlim=(-20,120) , ylim=(-15,15))
myPlot.map_dataframe(plot_hline,y='obs',z='z')
plt.show()

resulting plot

现在 seaborn 将函数的输出映射到 FacetGrid 的每个方面。请注意,如果您使用的绘图函数与 axhline 不同,您可能不一定需要从系列中提取值。

希望这对某人有所帮助!