箱线图显示了一组数据的最小值、最大值、平均值和标准差。

27
我想使用数据集的最小值、最大值、平均输出和标准差来创建一个箱线图。我找到的示例绘制了一个数值分布,但在我的情况下,这是不可行的。
有没有办法在Python(Matplotlib)中实现这个?

2
箱线图描述分位数。你无法从已有的数据中推导出这些信息。我建议不要创建一种带有均值、最小值、最大值和标准差的箱线图派生图,因为这会让熟悉箱线图的人感到困惑。而应该将均值、最小值、最大值表示成点(可能使用不同的符号或大小),并将标准差表示为误差线。 - Roland
2个回答

49
评论1.@Roland提出,非常重要:箱线图显示的是基本上不同的数量,如果您使用您拥有的数量制作类似的图表,可能会让用户感到困惑。我可以使用堆叠的errorbar图来表示这些信息。
import matplotlib.pyplot as plt
import numpy as np

# construct some data like what you have:
np.random.seed(2023)
x = np.random.randn(100, 8)
mins = x.min(0)
maxes = x.max(0)
means = x.mean(0)
std = x.std(0)

# create stacked errorbars:
plt.errorbar(np.arange(8), means, std, fmt='ok', lw=3)
plt.errorbar(np.arange(8), means, [means - mins, maxes - means],
             fmt='.k', ecolor='gray', lw=1)

enter image description here

1. 箱线图展示了分位数。你无法从现有数据中得出这些分位数。我建议不要创建一个带有均值、最小值、最大值和标准差的箱线图的派生图,因为这只会让熟悉箱线图的人感到困惑。我建议将均值、最小值、最大值表示为点(可能使用不同的符号或大小),将标准差表示为误差线。- Roland

1
errorbar() 的第一个参数为什么要使用 numpy(np.arange(8))?我认为 matplotlib 内部使用列表(列表的列表)。如果我错了,请纠正我。 - MasterControlProgram
1
matplotlib在内部使用numpy数组,并将任何输入转换为numpy数组:例如,type(plt.plot(range(10), range(10))[0].get_xdata())返回numpy.ndarray - jakevdp

0
根据可用的信息(均值、标准差、最小值、最大值),errorbar可能是唯一可以绘制的图形,但如果你想从聚合数据中绘制一个箱线图,matplotlib有一个可以使用的bxp()方法。请注意,这是一个Axes级别的函数(不能像plt.bxp那样调用)。它使用一个包含每个箱线图数据的字典列表。
然而,箱线图需要中位数、第一四分位数和第三四分位数,这些无法仅通过均值、标准差等推断出来,除非对数据集的分布做进一步的假设。
假设数据集服从正态分布。那么我们可以使用均值和标准差来估计中位数、第一四分位数和第三四分位数。利用这些值,我们还可以近似计算出须。假设没有异常值可用,我们可以按照以下方式绘制一个简单的箱线图。
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

# construct some data
x = np.random.default_rng(0).normal(size=(1000, 8))

means = x.mean(axis=0)
q1 = means + std * stats.norm.ppf(0.25)
q3 = means + std * stats.norm.ppf(0.75)
whislo = q1 - (q3 - q1)*1.5
whishi = q3 + (q3 - q1)*1.5

keys = ['med', 'q1', 'q3', 'whislo', 'whishi']
stats = [dict(zip(keys, vals)) for vals in zip(means, q1, q3, whislo, whishi)]
plt.subplot().bxp(stats, showfliers=False);

no fliers


现在假设我们可以访问中位数、第一四分位数和第三四分位数(下面的medianq1q3)。此外,让我们假设我们可以访问稍低于q1-(q3-q1)*1.5和稍高于q3+(q3-q1)*1.5的值,这些值可以用来定位盒须。另外,让我们假设我们可以访问盒须之外的值(fliers)。然后将所有这些信息传递给bxp()函数,绘制的图形与plt.boxplot函数绘制的完全相同。
# construct some data
x = np.random.default_rng(0).normal(size=(1000, 8))
median = np.median(x, axis=0)
q1 = np.quantile(x, 0.25, axis=0)
q3 = np.quantile(x, 0.75, axis=0)

# compute whiskers' locations
whislo = [np.min(x[x[:, i] > v, i]) for i, v in enumerate(q1 - (q3 - q1)*1.5)]
whishi = [np.max(x[x[:, i] < v, i]) for i, v in enumerate(q3 + (q3 - q1)*1.5)]
# identify fliers
fliers = [x[(x[:, i] < lo) | (x[:, i] > hi), i] for i, (lo, hi) in enumerate(zip(whislo, whishi))]

keys = ['med', 'q1', 'q3', 'whislo', 'whishi', 'fliers']
stats = [dict(zip(keys, vals)) for vals in zip(median, q1, q3, whislo, whishi, fliers)]

plt.subplot().bxp(stats);

full boxplot

你可以验证上述图是由同一个人绘制的。
plt.boxplot(x);

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