在 Python 中,计算百分位主要有两种方式,分别位于不同的库中:

- NumPy 库:
numpy.percentile() - Python 内置库 (Python 3.8+):
statistics.quantiles()
下面我们分别介绍它们的使用方法、区别和最佳实践。
使用 NumPy 的 numpy.percentile()
NumPy 是 Python 科学计算的核心库,其 percentile 函数功能强大且高效,尤其适合处理大型数值数组。
语法
numpy.percentile(a, q, axis=None, out=None, overwrite_input=False, interpolation='linear', keepdims=False)
参数说明
a: array_like,输入数据,可以是列表、元组或 NumPy 数组。q: float 或 array_like,要计算的百分位,取值范围在 0 到 100 之间,50 代表中位数,90 代表第 90 百分位数。axis: int 或 tuple of int,可选,指定计算百分位的轴,如果为None(默认),则将整个数组展平后计算。interpolation: str,可选,当指定的百分位位于两个数据点之间时,用于插值的方法,这是非常重要的一个参数。'linear'(默认): 线性插值,计算第 50 百分位数(中位数)时,如果数据点数量为偶数,会取中间两个数的平均值。'lower': 取较低的那个值。'higher': 取较高的那个值。'midpoint': 取两个值的中间值(平均值)。'nearest': 取最接近的那个值。
示例代码
import numpy as np
# 示例数据
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 1. 计算中位数 (第 50 百分位数)
median = np.percentile(data, 50)
print(f"数据: {data}")
print(f"第 50 百分位数 (中位数): {median}") # 输出: 5.5
# 2. 计算第 90 百分位数
p90 = np.percentile(data, 90)
print(f"第 90 百分位数: {p90}") # 输出: 9.1
# 3. 计算多个百分位数
p25, p50, p75 = np.percentile(data, [25, 50, 75])
print(f"第 25, 50, 75 百分位数: {p25}, {p50}, {p75}") # 输出: 3.25, 5.5, 7.75
# 4. 使用不同的插值方法
# 数据 [1, 2, 3, 4],计算第 50 百分位数
# 线性插值 (默认): (2+3)/2 = 2.5
# lower: 2
# higher: 3
# midpoint: (2+3)/2 = 2.5
# nearest: 2 (因为 2.5 距离 2 和 3 一样近,NumPy 会取较小的)
data_small = [1, 2, 3, 4]
print("\n数据:", data_small)
print(f"线性插值 (默认): {np.percentile(data_small, 50)}")
print(f"lower 插值: {np.percentile(data_small, 50, interpolation='lower')}")
print(f"higher 插值: {np.percentile(data_small, 50, interpolation='higher')}")
使用 Python 内置的 statistics.quantiles()
从 Python 3.8 开始,statistics 模块引入了 quantiles 函数,它提供了一种不依赖外部库的方式来计算分位数(百分位是其特例)。
语法
statistics.quantiles(data, *, n=4, method='exclusive')
参数说明
data: 可迭代对象,如列表或元组,包含数值数据。n: int,可选,要划分的分位数区间数量,默认为 4,即计算四分位数(第 25, 50, 75 百分位数)。method: str,可选,计算方法。'exclusive'(默认): 用于已排序的、不包含重复值的数据,计算方式与 NumPy 的默认行为略有不同。'inclusive': 用于包含重复值或未排序的数据。
示例代码
import statistics
# 示例数据
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 1. 计算四分位数 (默认 n=4, 即第 25, 50, 75 百分位数)
# 返回一个列表
quartiles = statistics.quantiles(data)
print(f"数据: {data}")
print(f"四分位数 (第 25, 50, 75 百分位数): {quartiles}") # 输出: [3.5, 5.5, 7.5]
# 2. 计算十分位数 (n=10, 即第 10, 20, ..., 90 百分位数)
deciles = statistics.quantiles(data, n=10)
print(f"十分位数 (第 10, 20, ..., 90 百分位数): {deciles}")
# 3. 计算百分位数 (n=100)
# 这会返回一个包含 99 个值的列表,表示第 1 到第 99 百分位数
# 我们可以从中提取我们需要的值
all_percentiles = statistics.quantiles(data, n=100)
p50_from_quantiles = all_percentiles[49] # 第 50 个百分位
p90_from_quantiles = all_percentiles[89] # 第 90 个百分位
print(f"通过 quantiles 计算的第 50 百分位数: {p50_from_quantiles}")
print(f"通过 quantiles 计算的第 90 百分位数: {p90_from_quantiles}")
Pandas 中的百分位计算
在进行数据分析时,数据通常存储在 Pandas 的 Series 或 DataFrame 中,Pandas 也提供了计算百分位的便捷方法。

语法
# 对于 Series Series.quantile(q=0.5, interpolation='linear') # 对于 DataFrame DataFrame.quantile(q=0.5, axis=0, numeric_only=True, interpolation='linear')
q: float 或 array-like,取值范围是 0.0 到 1.0(注意,这里是 0-1 之间的小数,而不是 0-100 的整数)。interpolation: 与 NumPy 相同,指定插值方法。
示例代码
import pandas as pd
import numpy as np
# 创建一个 Series
s = pd.Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
# 计算 50% 分位数 (即中位数)
median_s = s.quantile(0.5)
print(f"Series 的 50% 分位数: {median_s}") # 输出: 5.5
# 计算 90% 分位数
p90_s = s.quantile(0.9)
print(f"Series 的 90% 分位数: {p90_s}") # 输出: 9.1
# 计算多个分位数
quantiles_s = s.quantile([0.25, 0.5, 0.75])
print(f"Series 的多个分位数:\n{quantiles_s}")
# 创建一个 DataFrame
df = pd.DataFrame({
'A': [1, 2, 3, 4, 5],
'B': [10, 20, 30, 40, 50],
'C': ['a', 'b', 'c', 'd', 'e'] # 非数值列
})
# 计算每一列 (axis=0) 的中位数
median_df = df.quantile(0.5, axis=0, numeric_only=True)
print("\nDataFrame 每列的中位数:")
print(median_df)
# 计算每一行 (axis=1) 的 25% 分位数
quantile_rows = df.quantile(0.25, axis=1, numeric_only=True)
print("\nDataFrame 每行的 25% 分位数:")
print(quantile_rows)
总结与对比
| 特性 | numpy.percentile() |
statistics.quantiles() |
pandas.Series.quantile() |
|---|---|---|---|
| 来源 | NumPy 库 | Python 内置 (3.8+) | Pandas 库 |
输入 q |
0-100 的整数或数组 | 间接通过 n 参数 |
0-1 之间的小数或数组 |
| 主要用途 | 通用数值计算,大型数组 | 不依赖外部库,基础统计 | 数据分析,处理 Series/DataFrame |
| 灵活性 | 非常高,可指定任意插值方法 | 较低,主要计算等分位点 | 高,可指定插值方法,与 Pandas 生态无缝集成 |
| 依赖 | 需要安装 NumPy | 无需安装 | 需要安装 Pandas |
| 推荐场景 | - 进行科学计算或机器学习 - 处理大型 NumPy 数组 - 需要精确控制插值方法 |
- 在无法安装第三方库的环境下 - 进行简单的、基础的分位数计算 |
- 数据分析和处理流程中 - 数据已存在于 Pandas 结构中 |
如何选择?
- 如果你已经在使用 NumPy 或处理大型数组:直接使用
numpy.percentile(),它是最快、最灵活的选择。 - 如果你只是写一个简单的脚本,不想安装任何第三方库,且 Python 版本是 3.8+:可以使用
statistics.quantiles(),但对于单个百分位点的计算不如 NumPy 直接。 - 如果你在进行数据分析,数据在 Pandas 的 DataFrame 或 Series 中:毫无疑问,使用
pandas.Series.quantile()或pandas.DataFrame.quantile(),这是最方便、最符合 Pandas 使用习惯的方式。
