如何使用seaborn绘制成对直方图

6
我希望能够使用seaborn distplot绘制一个像这里展示的双柱状图。这种图也可以被称为背对背柱状图,或者是沿x轴翻转/镜像的双直方图,如此处所讨论。
以下是我的代码:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

green = np.random.normal(20,10,1000)
blue = np.random.poisson(60,1000)

fig, ax = plt.subplots(figsize=(8,6))

sns.distplot(blue, hist=True, kde=True, hist_kws={'edgecolor':'black'}, kde_kws={'linewidth':2}, bins=10, color='blue')
sns.distplot(green, hist=True, kde=True, hist_kws={'edgecolor':'black'}, kde_kws={'linewidth':2}, bins=10, color='green')
ax.set_xticks(np.arange(-20,121,20))
ax.set_yticks(np.arange(0.0,0.07,0.01))
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

plt.show()

这是输出结果: seaborn distplot

当我使用在这里讨论的方法(plt.barh)时,我得到了下面显示的条形图,这不是我想要的。 horizontal bar plot

或者我没有很好地理解解决方法…… 一个简单/短小的Python-seaborn-distplot实现类似于这些图的绘制将是完美的。我编辑了上面第一个图的图形以显示我希望实现的图形类型(尽管y轴不是倒置的): paired histogram

任何线索将不胜感激。

2个回答

7

您可以使用两个子图,倒转下面的y轴并使用相同的bin进行绘制。

df = pd.DataFrame({'a': np.random.normal(0,5,1000), 'b': np.random.normal(20,5,1000)})

fig =plt.figure(figsize=(5,5))
ax = fig.add_subplot(211)
ax2 = fig.add_subplot(212)

bins = np.arange(-20,40)

ax.hist(df['a'], bins=bins)
ax2.hist(df['b'],color='orange', bins=bins)
ax2.invert_yaxis()

这里输入图片描述

编辑:

@mwaskom建议的改进

fig, axes = plt.subplots(nrows=2, ncols=1, sharex=True, figsize=(5,5))

bins = np.arange(-20,40)

for ax, column, color, invert in zip(axes.ravel(), df.columns, ['teal', 'orange'],  [False,True]):
    ax.hist(df[column], bins=bins, color=color)
    
    if invert:
        ax.invert_yaxis()
        
plt.subplots_adjust(hspace=0)

enter image description here


很好,但是共享x轴,然后使用subplots_adjusth_pad调整为零,就会更好。 - mwaskom
@mwaskom非常好的想法!我很荣幸将它们包含在内。 - warped

6

使用 seaborn 的 displots 可以采用以下方法。Seaborn 不会返回创建的图形元素,但可以查询 ax。为了确保 ax 只包含您想要的倒置元素,这些元素可以先绘制出来。然后,所有的 patches(矩形条)和 lines(kde 的曲线)都可以给予负高度。可选地,可以使用 ax.spines['bottom'].set_position('zero') 将 x 轴设置为 y == 0

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

green = np.random.normal(20, 10, 1000)
blue = np.random.poisson(60, 1000)

fig, ax = plt.subplots(figsize=(8, 6))

sns.distplot(green, hist=True, kde=True, hist_kws={'edgecolor': 'black'}, kde_kws={'linewidth': 2}, bins=10,
             color='green')
for p in ax.patches:  # turn the histogram upside down
    p.set_height(-p.get_height())
for l in ax.lines:  # turn the kde curve upside down
    l.set_ydata(-l.get_ydata())

sns.distplot(blue, hist=True, kde=True, hist_kws={'edgecolor': 'black'}, kde_kws={'linewidth': 2}, bins=10,
             color='blue')
ax.set_xticks(np.arange(-20, 121, 20))
ax.set_yticks(np.arange(0.0, 0.07, 0.01))
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

pos_ticks = np.array([t for t in ax.get_yticks() if t > 0])
ticks = np.concatenate([-pos_ticks[::-1], [0], pos_ticks])
ax.set_yticks(ticks)
ax.set_yticklabels([f'{abs(t):.2f}' for t in ticks])
ax.spines['bottom'].set_position('zero')

plt.show()

example plot


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