如何使用Seaborn在同一图上绘制多个直方图

44
使用matplotlib,我可以在一个图上绘制两个数据集的直方图(一个紧挨着另一个,而不是重叠)。
import matplotlib.pyplot as plt
import random

x = [random.randrange(100) for i in range(100)]
y = [random.randrange(100) for i in range(100)]
plt.hist([x, y])
plt.show()

这产生了以下的图表。

enter image description here

然而,当我尝试使用seaborn来做这个的时候;
import seaborn as sns
sns.distplot([x, y])

我遇到了以下错误:
ValueError: color kwarg must have one color per dataset

所以我尝试添加一些颜色数值:
sns.distplot([x, y], color=['r', 'b'])

我遇到了同样的错误。我看到了关于如何叠加图形的这篇帖子,但我想要这些直方图并排显示,而不是叠加在一起。
同时,根据文档,它没有明确说明如何将一个列表的列表作为第一个参数'a'进行包含。
我该如何使用seaborn实现这种直方图的样式呢?
2个回答

55

如果我理解你的意思正确,你可能想尝试这个:

fig, ax = plt.subplots()
for a in [x, y]:
    sns.distplot(a, bins=range(1, 110, 10), ax=ax, kde=False)
ax.set_xlim([0, 100])

这应该会生成类似于这样的图形:

enter image description here

更新:

看起来你想要“seaborn外观”,而不是seaborn绘图功能。 为此,您只需要:

import seaborn as sns
plt.hist([x, y], color=['r','b'], alpha=0.5)

这将产生:

输入图像描述

更新:对于seaborn v0.12+:

seaborn v0.12+ 中,要获取 seaborn 风格的图形,您需要执行以下操作:

import seaborn as sns
sns.set_theme()  # <-- This actually changes the look of plots.
plt.hist([x, y], color=['r','b'], alpha=0.5)

更多信息请参阅seaborn文档


这看起来像是叠加的,但有没有一种方法可以让条形图并排而不是重叠在一起? - Malonge
你如何在seaborn中创建一个直方图,当你的分布、x和y的示例太大而无法保存在内存中时? - Thomas Matthew
3
@ThomasMatthew 这是一个好问题,但最好另开一篇问题来回答(也就是说,你需要提出“一个新问题”)。 - Primer
模块“seaborn”没有属性“plot”。 - user3103059
在你的第二段代码中(为直方图赋予“seaborn外观”),你在运行plt.hist()之前导入seaborn包是否有特别的原因? - jglad
导入 seaborn 的原因是为了获得 "seaborn look"(在导入时,它会将自己的样式应用于 matplotlib 样式表)。还要注意最近版本的 seaborn(需要额外的命令)。我已经更新了答案以反映这一点。 - Primer

8
将x和y合并到DataFrame中,然后使用histplot函数,并设置multiple='dodge'和hue参数。详见histplot
import random

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

x = [random.randrange(100) for _ in range(100)]
y = [random.randrange(100) for _ in range(100)]
df = pd.concat(axis=0, ignore_index=True, objs=[
    pd.DataFrame.from_dict({'value': x, 'name': 'x'}),
    pd.DataFrame.from_dict({'value': y, 'name': 'y'})
])
fig, ax = plt.subplots()
sns.histplot(
    data=df, x='value', hue='name', multiple='dodge',
    bins=range(1, 110, 10), ax=ax
)
ax.set_xlim([0, 100])

Resulting Plot


为什么要使用for _ in range()而不是for i in range()?请参见https://dev59.com/AW025IYBdhLWcg3wpHh-#5893946 - marianoju
@henry-ecker 为什么要重新排列导入的包? - marianoju
3
因为在这个理解中没有使用变量 i,我们调用函数 random.randrange(100) 时没有使用 range 函数产生的值,因此使用丢弃的变量更加恰当(以表明我们 没有 使用变量 i)。为遵循 PEP8 导入指南,必须重新排列包。“导入应按以下顺序分组:(1) 标准库导入。 (2) 相关的第三方导入... 每组导入之间应该放置一个空行。”@marianoju - Henry Ecker
如果我想使用实际的数据框而不是模拟的范围怎么办?类似这样:x = df ['Rating1']y = df ['Rating2']。语法会是什么样子?谢谢。 - Edison
如果您的数据集大小不同,并且希望比较它们的个别概率,请添加 stat='probability', common_norm=False - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接