我的目标是在使用seaborn制作的地块上绘制y = 0的水平红线:sns.lmplot
由col=
或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=
和/或row=
生成一系列地块的情况,我们希望跟踪该行每个情节。
答案 0 :(得分:4)
所以这段代码适用于我们使用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()
不确定为什么水平线的颜色是每个单独情节上使用的最后一种颜色,但我暂时放弃了这一点:)
答案 1 :(得分:3)
由于我遇到了这个寻找答案,这是我最终发现的更一般的答案:
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只能为y
获取单个值。 (请记住,在我们的例子中,每个样本都有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()
现在seaborn将您函数的输出映射到FacetGrid
的每个方面。请注意,如果您使用的是与axhline不同的绘图函数,则可能不一定需要从该系列中提取该值。
希望这有助于某人!
答案 2 :(得分:1)
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