Polars:高效获取第二大元素或小n值下的第n大元素
Polars:高效获取第二大元素或小n值下的第n大元素
嘿,这个问题问到点子上了!在Polars里处理这类「取第n大元素(尤其是n远小于列的总规模)」的需求,完全没必要给整个列做全量排序——那样太浪费资源了,咱有更高效的玩法,我给你拆解清楚:
核心高效方法:top_k()
当n很小的时候,top_k(n)绝对是首选!它的原理是维护一个大小为n的堆,只找出列中最大的n个元素,时间复杂度是O(m)(m是列的行数),比全排序的O(m log m)高效太多,特别适合n远小于m的场景。
举个实际的例子,先创建一个测试DataFrame:
import polars as pl # 构造包含重复值的测试数据 df = pl.DataFrame({"values": [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]})
获取第二大元素
我们只需要取最大的2个元素,然后取其中的第二个(也就是第二大的那个):
second_largest = df.select(pl.col("values").top_k(2).nth(1)).item() print(second_largest) # 输出:6
这里top_k(2)会返回降序排列的前2大元素[9,6],用nth(1)就能拿到第二大的元素;如果你习惯用last()也可以,效果是一样的。
通用获取第n大元素
把逻辑推广到任意小n的情况,只需要把top_k的参数设为n,再取索引n-1的元素就行:
n = 3 third_largest = df.select(pl.col("values").top_k(n).nth(n-1)).item() print(third_largest) # 输出:5
去重后的第n大元素
如果你的需求是去重后的第n大元素,只需要在top_k前加个unique()就行:
# 去重后的第二大元素 second_largest_unique = df.select(pl.col("values").unique().top_k(2).nth(1)).item() print(second_largest_unique) # 输出:5
避坑提醒:别用全量排序
可能有人会想到先排序再取第n个元素,比如pl.col("values").sort(reverse=True).nth(1)——这种方法在n很小的时候完全没必要,全量排序会对整个列做排序操作,数据量一大性能差距就会很明显,所以优先用top_k就对了!
备注:内容来源于stack exchange,提问作者Test
相关产品推荐
相关产品推荐

