首页 > 解决方案 > Python Matplotlib - “加权”箱线图

问题描述

我正在尝试创建一个具有指定数字的箱线图,该数字表示该值在数据中出现的次数。

我有的:

import numpy as np
import matplotlib.pyplot as plt

data = np.array([[[0, 1, 2, 3], [31, 84, 2, 1]], [[0, 1, 2], [17, 104, 21]], [[0, 1, 2, 3, 4], [17, 106, 61, 3, 1]]])
plt.boxplot([data[0][0], data[1][0], data[2][0]])

输出:

在此处输入图像描述

我想要的是:

我知道我可以做类似的事情:(对于每个盒子)

merged_list_box1 = np.array([])
np.append(merged_list_box1, data[0][1][0]*31)
np.append(merged_list_box1, data[0][1][1]*84)
.
.
.

但是由于我拥有的数据集,1个盒子的一些merged_list的长度将超过500。我有大约20个这样的盒子。有没有更有效的方法?

提前致谢!

标签: pythonnumpymatplotlibplotgraph

解决方案


首先,当前版本的 numpy 给出了弃用警告,因为如果每个子列表具有相同数量的元素,列表列表只能转换为 numpy 数组。将这样的列表列表转换为 numpy 格式只会保留列表格式的列表。

另请注意,这np.append()是一个缓慢的操作,在每一步创建数组的完整副本,应谨慎使用。请参阅例如如何在不将结果重新分配给新变量的情况下附加到 numpy 数组?.

要重复列表中的每个元素,可以通过 来完成第二个列表中给出的次数np.repeat()。生成的具有 500 个元素的 numpy 数组不是问题。因此,代码可能如下所示:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator

data = np.array([[[0, 1, 2, 3], [31, 84, 2, 1]], [[0, 1, 2], [17, 104, 21]], [[0, 1, 2, 3, 4], [17, 106, 61, 3, 1]]])
# or, better, just data = [[[0, 1, 2, 3], [31, 84, 2, 1]], [[0, 1, 2], [17, 104, 21]], [[0, 1, 2, 3, 4], [17, 106, 61, 3, 1]]]
plt.boxplot([np.repeat(d[0], d[1]) for d in data])
plt.gca().yaxis.set_major_locator(MaxNLocator(integer=True))
plt.show()

结果图

在这个例子中,第二个“盒子”看起来像一条线,因为第一个和第三个四分位数都等于1。由于所有输入值都是整数,因此示例代码强制刻度为整数。

假设所有第一个子列表只是从零开始的数字序列,则可以稍微简化数据。

data = [[31, 84, 2, 1], [17, 104, 21], [17, 106, 61, 3, 1]]
plt.boxplot([np.repeat(np.arange(len(d)), d) for d in data])

推荐阅读