在 seaborn.jointplot 中绘制两个分布

Posted

技术标签:

【中文标题】在 seaborn.jointplot 中绘制两个分布【英文标题】:Plotting two distributions in seaborn.jointplot 【发布时间】:2015-10-10 22:51:04 【问题描述】:

我有两个 pandas 数据框,我想在同一个 seaborn jointplot 中进行绘图。它看起来像这样(命令在 IPython shell 中使用;ipython --pylab):

import pandas as pd
import seaborn as sns
iris = sns.load_dataset('iris')
df = pd.read_csv('my_dataset.csv')
g = sns.jointplot('sepal_length', 'sepal_width', iris)

两个数据帧中的键是相同的。 如何在同一个图中绘制我的值(当然颜色不同)?甚至更详细:我如何绘制两个数据集,但只有第一个的分布在顶部和侧面? IE。只画点。

【问题讨论】:

我怀疑这是最好的方法,但您可以使用pairplothue 选项来获得不同的颜色(在第一次合并数据集之后)。 stanford.edu/~mwaskom/software/seaborn/examples/… 顺便说一句,现在建议在启动 ipython 后使用 %matplotlib inline 而不是使用 --pylab 调用 --pylab%matplotlib inline有什么区别? 对于您的第一条评论。我更喜欢@jianxun-li 给出的解决方案。 新的 Seaborn v0.11 版本通过 hue 参数优雅地解决了您的问题。在这里查看我的答案:***.com/a/63843331/7952162 【参考方案1】:

这是通过修改sns.JointGrid的基础数据来实现的一种方法。

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

# simulate some artificial data
# ========================================
np.random.seed(0)
data1 = np.random.multivariate_normal([0,0], [[1,0.5],[0.5,1]], size=200)
data2 = np.random.multivariate_normal([0,0], [[1,-0.8],[-0.8,1]], size=100)

# both df1 and df2 have bivaraite normals, df1.size=200, df2.size=100
df1 = pd.DataFrame(data1, columns=['x1', 'y1'])
df2 = pd.DataFrame(data2, columns=['x2', 'y2'])


# plot
# ========================================   
graph = sns.jointplot(x=df1.x1, y=df1.y1, color='r')

graph.x = df2.x2
graph.y = df2.y2
graph.plot_joint(plt.scatter, marker='x', c='b', s=50)

【讨论】:

@DanielThaagaardAndreasen 不客气。很高兴它有帮助。 :-) 如何在侧面的直方图中也显示第二个分布? @JianxunLi 关于添加图例的巧妙方法有什么技巧吗? @user1834164 graph.plot_marginals(plt.hist, c='b') @NimrodMorag - 您建议的代码返回错误AttributeError: 'Rectangle' object has no property 'vertical'。 @ManuCJ - 感谢您提供指向新 hue 参数的示例,但是,这不如将任何两个不相关的数据集绘制在一起那样通用。我仍然想要@user1834164 问题的另一个答案。【参考方案2】:

在我看来,更好的解决方案是将坐标轴句柄用于sns.joinplot 返回的联合分布和边际分布。使用这些(名称为ax_jointax_marg_xax_marg_y)也可以绘制边际分布图。

import seaborn as sns
import numpy as np

data1 = np.random.randn(100)
data2 = np.random.randn(100)
data3 = np.random.randn(100)
data4 = np.random.randn(100)

df1 = pd.DataFrame('col1': data1, 'col2':data2)
df2 = pd.DataFrame('col1': data3, 'col2':data4)

axs = sns.jointplot('col1', 'col2', data=df1)
axs.ax_joint.scatter('col1', 'col2', data=df2, c='r', marker='x')

# drawing pdf instead of histograms on the marginal axes
axs.ax_marg_x.cla()
axs.ax_marg_y.cla()
sns.distplot(df1.col1, ax=axs.ax_marg_x)
sns.distplot(df1.col2, ax=axs.ax_marg_y, vertical=True)

【讨论】:

我能够重现您的代码,但是,我想在垂直边缘轴上绘制一个新的直方图(而不是您的示例中的 sns.distplot 图)。我尝试改用函数sns.histplot,但结果最终旋转了90度。如何在垂直边缘轴上添加新的直方图? @Stefano 尝试在我在答案中提供的 sn-p 末尾添加以下 2 行:df_new = pd.DataFrame('col1': np.random.rand(100)) sns.histplot(data=df_new, ax=axs.ax_marg_y, y="col1", stat="density")【参考方案3】:

在绘制jointplot之后可能会更容易,更改为您想要绘制某些东西的轴,然后使用普通的pyplot或基于轴的seaborn plots:

g=sns.jointplot(...)
plt.sca("axis_name")
plt.plot/plt.scatter/.../sns.kde(ax="axis_name")

轴名称为ax_joint(用于二维图)或ax_marg_xax_marg_y(用于侧面的一维图)。

此外,如果您想使用jointplot 结构但通过pyplot 绘制所有图,请使用cla 函数,例如清除二维图:

g.ax_joint.cla()

【讨论】:

【参考方案4】:
sns.jointplot(data=penguins, x="bill_length_mm", y="bill_depth_mm", hue="species")

【讨论】:

以上是关于在 seaborn.jointplot 中绘制两个分布的主要内容,如果未能解决你的问题,请参考以下文章

如何绘制非方形 Seaborn jointplot 或 JointGrid

seaborn使用jointplot函数为散点图添加边缘图为散点图添加边缘直方图(Marginal Plot in Python with Seaborn jointplot)

在gnuplot中绘制两个轴

如何在 seaborn 中并排绘制两个计数图?

在两个纬度和经度之间绘制折线

R Normalize 然后在 R 中一起绘制两个直方图