使用matplotlib.pyplot
中的boxplot
,通过包含中位数来计算四分位值。可以将其更改为不包括中位数吗?
例如,考虑有序数据集
2、3、4、5、6、7、8
如果不包括中位数,则 Q1=3,Q3=7。但是,boxplot
包含中值,即 5,并生成下图
是否可以改变这种行为,并且在四分位数的计算中不包括中位数?这应该对应于维基百科页面 Quartile 上描述的方法 1。 。下面列出了生成图形的代码
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator
data = [2, 3, 4, 5, 6, 7, 8]
fig = plt.figure(figsize=(6,1))
ax = fig.add_axes([0.1,0.25,0.8,0.8])
bp = ax.boxplot(data, '',
vert=False,
positions=[0.4],
widths=[0.3])
ax.set_xlim([0,9])
ax.set_ylim([0,1])
ax.xaxis.set_major_locator(MultipleLocator(1))
ax.spines["right"].set_visible(False)
ax.spines["left"].set_visible(False)
ax.spines["top"].set_visible(False)
ax.yaxis.set_ticks([])
ax.grid(which='major',axis='x',lw=0.1)
plt.show()
最佳答案
提出这个问题的原因是,互联网上的一些教育资源并未将四分位数计算为 matplotlib 箱线图使用的默认设置。例如,在线类(class)中"Statistics and probability"来自可汗学院,四分位数的计算方法如维基百科页面 Quartiles 上的方法 1 中所述。 ,而箱线图采用方法 2。
考虑可汗学院类(class)“统计和概率”部分 "Comparing range and interquartile range (IQR)" 中的一个示例。密歇根州帕拉代斯有每日高温记录。连续7天,发现温度为16、24、26、26、26、27和28摄氏度。用箱线图描述数据并计算 IQR。
箱线图中使用默认设置的结果与Khan教授给出的结果有很大不同,见下图。
matplotlib 发现的 IQR 是 1.5,Khan 教授计算的 IQR 是 3。 正如@JohanC 的评论中指出的,boxplot 不能直接配置为遵循方法 1,而是需要自定义函数。因此,忽略异常值的计算,我更新了代码,按照方法1计算四分位数,从而与可汗学院的类(class)具有可比性。下面列出了代码,不太Pythonic,欢迎提出建议。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
from matplotlib.ticker import MultipleLocator
def median(x):
"""
x - input a list of numbers
Returns the midpoint number, for example
in a list with oddnumbers
[1,2, 3, 4,5] returns 3
for a list with even numbers the algebraic mean is returned, e.g
[1,2,3,4] returns 2.5
"""
if len(x)&1:
# Odd number of elements in list, e.g. x = [1,2,3] returns 2
index_middle = int((len(x)-1)/2)
median = x[index_middle]
else:
# Even number of elements in list, e.g. x = [-1,2] returns 0.5
index_lower = int(len(x)/2-1)
index_upper = int(len(x)/2)
median = (x[index_lower]+x[index_upper])/2
return median
def method_1_quartiles(x):
"""
x - list of numbers
"""
x.sort()
N = len(x)
if N&1:
# Odd number of elements
index_middle = int((N-1)/2)
lower = x[0:index_middle] # Up to but not including
upper = x[index_middle+1:N+1]
Q1= median(lower)
Q2 = x[index_middle]
Q3 = median(upper)
else:
# Even number of elements
index_lower = int(N/2)
lower = x[0:index_lower]
upper = x[index_lower:N]
Q1= median(lower)
Q2 = (x[index_lower-1]+x[index_lower])/2
Q3 = median(upper)
return Q1,Q2,Q3
data = [16,24,26, 26, 26,27,28]
fig = plt.figure(figsize=(6,1))
ax = fig.add_axes([0.1,0.25,0.8,0.8])
stats = cbook.boxplot_stats(data,)[0]
Q1_default = stats['q1']
Q3_default = stats['q3']
stats['whislo']=min(data)
stats['whishi']=max(data)
IQR_default = Q3_default - Q1_default
Q1, Q2, Q3 = method_1_quartiles(data)
IQR = Q3-Q1
stats['q1'] = Q1
stats['q3'] = Q3
print(f"IQR: {IQR}")
ax.bxp([stats],vert=False,manage_ticks=False,widths=[0.3],positions=[0.4],showfliers=False)
ax.set_xlim([15,30])
ax.set_ylim([0,1])
ax.xaxis.set_major_locator(MultipleLocator(1))
ax.spines["right"].set_visible(False)
ax.spines["left"].set_visible(False)
ax.spines["top"].set_visible(False)
ax.yaxis.set_ticks([])
ax.grid(which='major',axis='x',lw=0.1)
plt.show()
生成的图表是
关于Matplotlib boxplot select方法计算四分位数值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66725463/