杰瑞科技汇

Python quantile函数如何计算分位数?

  1. 核心概念:什么是分位数?
  2. NumPy 中的 quantile 函数 (最常用)
  3. Pandas 中的 quantile 方法 (Series/DataFrame)
  4. SciPy 中的 scoreatpercentile 函数
  5. 如何选择?
  6. 完整代码示例

核心概念:什么是分位数?

分位数是将一个数据集划分为大小相等(或近似相等)的连续区间的数值点,通俗地说,它回答了“数据集中某个百分比的数据点小于或等于这个值?”这个问题。

Python quantile函数如何计算分位数?-图1
(图片来源网络,侵删)

常见的分位数包括:

  • 中位数:第 50 百分位数,将数据集平分为两部分。
  • 四分位数
    • 第 1 四分位数 (Q1):第 25 百分位数。
    • 第 3 四分位数 (Q3):第 75 百分位数。
  • 十分位数:将数据集分为 10 份的 9 个点。
  • 百分位数:将数据集分为 100 份的 99 个点。

关键点:分位数的计算有多种方法(尤其是在数据点数量有限时),不同库或不同参数可能会得到略微不同的结果,最常用的是线性插值法。


NumPy 中的 numpy.quantile()

这是 NumPy 库中计算分位数的核心函数,也是最直接、最常用的方法之一。

语法

numpy.quantile(a, q, axis=None, out=None, overwrite_input=False, method='linear', keepdims=False)

参数说明

  • a: array_like,输入的数组或列表。
  • q: float 或 array_like,要计算的分位数,取值范围在 [0, 1] 之间。5 表示中位数,[0.25, 0.5, 0.75] 表示计算三个四分位数。
  • axis: int 或 tuple of ints, optional,指定计算分位数的轴,如果为 None (默认),则将数组展平后计算。
  • method: str, optional,指定计算分位数的方法,这是不同库结果差异的主要来源,可选值:
    • 'linear' (默认): 线性插值,这是最常用、最标准的算法。
    • 'lower': 取最近的较低值。
    • 'higher': 取最近的较高值。
    • 'midpoint': 取两个最近值的中间值。
    • 'nearest': 取最近的值。
  • keepdims: bool, optional,如果为 True,则在输出中保留缩减的维度。

示例

import numpy as np
# 创建一个示例数据集
data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
# 1. 计算中位数 (第50百分位数)
median = np.quantile(data, 0.5)
print(f"中位数 (50%): {median}")  # 输出: 5.5
# 2. 计算多个分位数 (四分位数)
quartiles = np.quantile(data, [0.25, 0.5, 0.75])
print(f"四分位数 (25%, 50%, 75%): {quartiles}")
# 输出: [3.25 5.5  7.75]
# 3. 指定不同的计算方法
# 使用 'lower' 方法
q_lower = np.quantile(data, 0.9, method='lower')
# 使用 'higher' 方法
q_higher = np.quantile(data, 0.9, method='higher')
print(f"90%分位数 (lower方法): {q_lower}")  # 输出: 9
print(f"90%分位数 (higher方法): {q_higher}") # 输出: 10

Pandas 中的 Series.quantile()DataFrame.quantile()

在 Pandas 中,quantile 是一个方法,可以直接应用于 Series(一维数据)和 DataFrame(二维数据)。

Python quantile函数如何计算分位数?-图2
(图片来源网络,侵删)

语法

Series.quantile(q=0.5, interpolation='linear')
DataFrame.quantile(q=0.5, axis=0, numeric_only=True, interpolation='linear')

参数与 NumPy 类似,但有几个不同点:

  • q 参数在 Pandas 中默认值是 5
  • interpolation 参数与 NumPy 的 method 作用相同,但名称不同。
  • 对于 DataFrame,axis=0 (默认) 表示按列计算,axis=1 表示按行计算。
  • numeric_only 是 Pandas 特有的,确保只对数值列进行计算。

示例

import pandas as pd
import numpy as np
# 创建一个 Pandas Series
s = pd.Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
# 1. 计算中位数 (默认q=0.5)
median_s = s.quantile()
print(f"Series中位数: {median_s}") # 输出: 5.5
# 2. 计算四分位数
quartiles_s = s.quantile([0.25, 0.5, 0.75])
print(f"Series四分位数:\n{quartiles_s}")
# 输出:
# 0.25    3.25
# 0.50    5.50
# 0.75    7.75
# Name: value, dtype: float64
# 创建一个 Pandas DataFrame
df = pd.DataFrame({
    'A': [1, 2, 3, 4, 5],
    'B': [10, 20, 30, 40, 50],
    'C': ['a', 'b', 'c', 'd', 'e'] # 非数值列
})
# 3. 计算每一列的分位数 (默认axis=0)
# numeric_only=True 会自动忽略'C'列
df_quartiles = df.quantile([0.25, 0.75], numeric_only=True)
print(f"\nDataFrame列分位数:\n{df_quartiles}")
# 输出:
#        A     B
# 0.25  2.0  20.0
# 0.75  4.0  40.0
# 4. 计算每一行的分位数 (axis=1)
# 需要先将所有列转为数值类型,或者选择数值列
row_quartiles = df[['A', 'B']].quantile(0.5, axis=1)
print(f"\nDataFrame行中位数:\n{row_quartiles}")
# 输出:
# 0     5.5
# 1    11.0
# 2    16.5
# 3    22.0
# 4    27.5
# Name: 0.50, dtype: float64

SciPy 中的 scipy.stats.scoreatpercentile()

SciPy 的统计模块也提供了分位数计算功能,但函数名和参数略有不同。

语法

scipy.stats.scoreatpercentile(a, per, limit=(), interpolation_method='fraction')

参数说明

  • a: array_like,输入数组。
  • per: float 或 array_like。百分位数,取值范围在 [0, 100] 之间,注意这里是百分比,不是小数!
  • interpolation_method: str,指定插值方法。
    • 'fraction' (默认): 线性插值。
    • 'lower', 'higher', 'midpoint', 'nearest': 与 NumPy 类似。

示例

from scipy import stats
import numpy as np
data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
# 计算中位数 (第50百分位数)
# 注意这里的参数是 50, 不是 0.5
median_scipy = stats.scoreatpercentile(data, 50)
print(f"SciPy中位数 (50%): {median_scipy}") # 输出: 5.5
# 计算第90百分位数
q90_scipy = stats.scoreatpercentile(data, 90)
print(f"SciPy 90%分位数: {q90_scipy}") # 输出: 9.9

如何选择?

库/函数 优点 缺点 适用场景
numpy.quantile() 最直接、最常用,语法清晰,q参数是小数,符合直觉。 需要先导入NumPy。 计算单个或多个NumPy数组的分位数,是数据科学任务中的首选。
pandas.Series.quantile() 与Pandas数据结构无缝集成,可以方便地对DataFrame的列或行进行操作。 需要先创建Pandas对象。 在数据分析流程中,当你已经有一个DataFrame或Series时,直接调用此方法非常方便。
scipy.stats.scoreatpercentile() SciPy统计工具箱的一部分,功能强大。 参数per是百分比,容易与q混淆,不如NumPy/Pandas常用。 当你已经在使用SciPy进行其他统计计算时,可以顺手使用,或者当需要计算百分位数(0-100)时。

总结建议

  • 如果你手头的是一个NumPy数组,或者只是一个简单的列表,并且想快速计算分位数,numpy.quantile()
  • 如果你正在使用Pandas进行数据分析,处理的是DataFrame或Series,df.quantile()s.quantile(),因为它更符合Pandas的操作习惯。
  • scipy.stats.scoreatpercentile() 是一个不错的选择,但使用频率相对较低,主要需要注意参数是百分比。

完整代码示例

下面是一个综合示例,展示了不同库计算结果的对比。

Python quantile函数如何计算分位数?-图3
(图片来源网络,侵删)
import numpy as np
import pandas as pd
from scipy import stats
# 1. 准备数据
data_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
data_np = np.array(data_list)
data_series = pd.Series(data_list)
# 要计算的分位数
q_to_calculate = [0.25, 0.5, 0.75, 0.9]
print("--- 原始数据 ---")
print(data_list)
print(f"\n计算分位数: {q_to_calculate}\n")
# 2. 使用 NumPy
print("--- NumPy 结果 ---")
np_results = np.quantile(data_np, q_to_calculate)
for q, res in zip(q_to_calculate, np_results):
    print(f"  {q*100:.0f}% 分位数: {res}")
print()
# 3. 使用 Pandas
print("--- Pandas 结果 ---")
pd_results = data_series.quantile(q_to_calculate)
print(pd_results)
print()
# 4. 使用 SciPy (注意参数是百分比)
print("--- SciPy 结果 ---")
scipy_per = [p * 100 for p in q_to_calculate]
scipy_results = stats.scoreatpercentile(data_np, scipy_per)
for per, res in zip(scipy_per, scipy_results):
    print(f"  {per:.0f}% 分位数: {res}")
print()
# 5. 演示不同插值方法的结果
print("--- 不同插值方法对比 (计算90%分位数) ---")
data_for_method = np.array([1, 2, 3, 4, 5])
print(f"数据: {data_for_method}")
print(f"线性插值 (默认): {np.quantile(data_for_method, 0.9)}")
print(f"取较低值: {np.quantile(data_for_method, 0.9, method='lower')}")
print(f"取较高值: {np.quantile(data_for_method, 0.9, method='higher')}")
print(f"取最近值: {np.quantile(data_for_method, 0.9, method='nearest')}")

这个例子清晰地展示了,对于相同的数据和相同的分位数定义,不同的库(使用默认参数)会给出相同的结果,但它们的接口和侧重点有所不同,理解这些差异有助于你在不同的场景下选择最合适的工具。

分享:
扫描分享到社交APP
上一篇
下一篇