直接调用 pandas.series.rank(pct=true, method='min') 可得 0–1 区间百分比排名,反映各值在列内的相对位置比例;pct=true 是关键,method 控制并列处理,nan 默认跳过,多列推荐 df[['a','b']].rank(pct=true)。

用 pandas.Series.rank 计算单列百分比排名
直接调用 rank 方法并设置 method='min' 和 pct=True 即可得到 0–1 区间的百分比排名(即第 p 百分位位置)。注意:这不是“前 x%”的阈值判断,而是每个值在其列中所处的相对位置比例。
-
pct=True是关键参数,它把原始 rank 值线性映射到 [0, 1] 区间;不加它返回的是整数排名(如 1、2、3…) -
method影响并列值的处理:'min'(默认)对相同值分配最小名次,'average'取平均名次,'dense'保证名次连续,选哪个取决于业务定义 - NaN 默认被跳过(
na_option='keep'可改为保留为 NaN 排名)
示例:
import pandas as pd s = pd.Series([10, 20, 20, 30]) s.rank(pct=True, method='min')结果为
0.0、0.25、0.25、1.0 —— 四个数,最小值排在 0%,最大值排在 100%,并列值共享同一百分位。
对 DataFrame 多列分别做百分比排名
别用循环逐列调用 rank,直接传入列名列表或用 apply 更简洁安全。但要注意:每列独立计算,不跨列归一化。
- 推荐写法:
df[['col_a', 'col_b']].rank(pct=True)—— 返回新 DataFrame,原 df 不变 - 就地更新可用:
df[['col_a', 'col_b']] = df[['col_a', 'col_b']].rank(pct=True) - 避免
df.apply(lambda x: x.rank(pct=True)),它隐式按列 axis=0 执行,但容易因索引错位或 dtype 混合出问题
如果某列含非数值类型(如字符串),rank 会报 TypeError: cannot convert type 'object' to numeric,需提前清洗或筛选数值列。
百分比排名结果不是“Top N%”布尔标签
很多人误以为 rank(pct=True) 输出就是“是否属于前 5%”的 True/False,其实它只是位置度量。要转成分类标签,必须手动阈值比较。
- 例如取前 10%:
df['col'].rank(pct=True) - 注意边界:
- 若严格控制数量(比如只取前 10 行),该用
nlargest(10)或sort_values().head(10),而非依赖 pct 阈值
另外,pct=True 的结果受样本量影响明显:3 行数据的百分比排名只有 0.0、0.5、1.0 三个取值,无法精细区分。
性能与 dtype 注意事项
对大型 DataFrame 调用 rank 时,float64 列最快,category 或含大量 NaN 的列会慢 2–3 倍。pandas 1.4+ 后,rank 默认使用 engine='numba' 加速,但仅对数值列生效。
- 确保目标列为数值型:
df['col'] = pd.to_numeric(df['col'], errors='coerce'),否则rank报错或静默失败 - 避免在链式操作中多次调用
rank,比如df.assign(rank=df.col.rank(pct=True)).query('rank > 0.9')比分开写更高效 - 如果只需 Top K 排名,用
Series.nlargest(k).rank(pct=True)会比全量 rank 再过滤快得多
真正容易被忽略的是:百分比排名本质是顺序统计量,它对异常值不敏感,但对重复值极其敏感 —— 一堆相同的最大值会让 100% 排名覆盖远超预期的行数。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











