Matplotlib boxplot select方法计算四分位数值

标签 matplotlib boxplot quartile

使用matplotlib.pyplot中的boxplot,通过包含中位数来计算四分位值。可以将其更改为不包括中位数吗?

例如,考虑有序数据集

2、3、4、5、6、7、8

如果不包括中位数,则 Q1=3,Q3=7。但是,boxplot 包含中值,即 5,并生成下图

Boxplot

是否可以改变这种行为,并且在四分位数的计算中不包括中位数?这应该对应于维基百科页面 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教授给出的结果有很大不同,见下图。

Boxplots with Quartiles calculated according to Method 1 and 2

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()

生成的图表是

Boxplot with quartiles according to Method 1

关于Matplotlib boxplot select方法计算四分位数值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66725463/

相关文章:

python - pcolormesh 内存使用

python - 使用 matplotlib imshow 和 scatter 获得相同的子图大小

python - 一系列列数据的散点图

r - 使用与 hist() 和plot() 配合使用的替代命令时出现箱线图错误

python - 如何让 matplotlib 在 IPython 下工作?

python - 如何调整seaborn中的子图大小?

javascript - 如何在 plotly.js 中为箱形图设置固定的分类范围

mysql - 数据库项目排名可移动权重

python - 如何在 matplotlib 箱线图中标记四分位数?