如何使用类似 KDnuggets 样式的 PDF 绘制比较箱线图

How to plot Comparative Boxplot with a PDF like KDnuggets Style

在浏览 Understanding Boxplots from the KDnuggets Article 时。我找到了带有概率密度函数的 Boxplot 的详细图 (pdf)

我正在尝试绘制比较箱线图和概率密度函数 (pdf),如下图文章中所示

我知道单独绘制基本 box plot and pdf。我的可视化知识是 minimum.I 我不要求精确复制上述图,非常感谢具有详细信息的类似图。

我乐于接受新的想法和方法,并希望在开始之前试探一下

是否可以用Python绘制上面的图如果是,将使用哪个包来绘制上面的图?有人可以阐明用 Python 绘制上述图吗?我很乐意收到您的任何线索。

这里尝试重新创建情节的图形元素。使用一些随机数据而不是完美的正态分布,因此您可以插入自己的数据。 (要获得更完美的曲线,请生成更多的样本。)

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

x = np.random.normal(0, 1, 1000)
mean = x.mean()
std = x.std()
q1, median, q3 = np.percentile(x, [25, 50, 75])
iqr = q3 - q1

fig, (ax1, ax2) = plt.subplots(nrows=2, sharex=True)

medianprops = dict(linestyle='-', linewidth=2, color='yellow')
sns.boxplot(x=x, color='lightcoral', saturation=1, medianprops=medianprops,
            flierprops={'markerfacecolor': 'mediumseagreen'}, whis=1.5, ax=ax1)

ticks = [mean + std * i for i in range(-4, 5)]
ticklabels = [f'${i}\sigma$' for i in range(-4, 5)]
ax1.set_xticks(ticks)
ax1.set_xticklabels(ticklabels)
ax1.set_yticks([])
ax1.tick_params(labelbottom=True)
ax1.set_ylim(-1, 1.5)
ax1.errorbar([q1, q3], [1, 1], yerr=[-0.2, 0.2], color='black', lw=1)
ax1.text(q1, 0.6, 'Q1', ha='center', va='center', color='black')
ax1.text(q3, 0.6, 'Q3', ha='center', va='center', color='black')
ax1.text(median, -0.6, 'median', ha='center', va='center', color='black')
ax1.text(median, 1.2, 'IQR', ha='center', va='center', color='black')
ax1.text(q1 - 1.5*iqr, 0.4, 'Q1 - 1.5*IQR', ha='center', va='center', color='black')
ax1.text(q3 + 1.5*iqr, 0.4, 'Q3 + 1.5*IQR', ha='center', va='center', color='black')
# ax1.vlines([q1 - 1.5*iqr, q1, q3, q3 + 1.5*iqr], 0, -2, color='darkgrey', ls=':', clip_on=False, zorder=0)

sns.kdeplot(x, ax=ax2)
kdeline = ax2.lines[0]
xs = kdeline.get_xdata()
ys = kdeline.get_ydata()

ylims = ax2.get_ylim()
ax2.fill_between(xs, 0, ys, color='mediumseagreen')
ax2.fill_between(xs, 0, ys, where=(xs >= q1 - 1.5*iqr) & (xs <= q3 + 1.5*iqr), color='skyblue')
ax2.fill_between(xs, 0, ys, where=(xs >= q1) & (xs <= q3), color='lightcoral')
# ax2.vlines([q1 - 1.5*iqr, q1, q3, q3 + 1.5*iqr], 0, 100, color='darkgrey', ls=':', zorder=0)
ax2.set_ylim(0, ylims[1])
plt.show()

一些备注:

  • 通常中位数和均值不重合,因此 0 西格玛可能会偏离中线。
  • Matplotlib 在最接近计算的Q1 - 1.5 IQRQ3 + 1.5 IQR的数据点绘制胡须,所以当点数不多时,胡须的位置可能是有点偏了。
  • 对于真实数据,分布很少看起来像完美的钟形曲线。

这里有一个 100 万个样本的例子: