如何在Polars中过滤列表内出现至少两次的元素(不使用apply)
Polars过滤子列表:保留出现至少两次的元素(无apply实现)
给定包含子列表的Polars Series,要过滤每个子列表仅保留出现次数≥2的元素,且不使用apply方法,具体实现如下:
完整代码
import polars as pl ser = pl.Series([[1,2,1,4], [3, 3, 3, 4], [1,2,3,4]]) # 转换为带索引的DataFrame,方便后续按原列表分组 df = ser.to_frame(name="lists").with_row_index("index") # 展开元素、计算出现次数、过滤后重新聚合 result = ( df.explode("lists") .rename({"lists": "element"}) # 用窗口函数计算每个元素在对应原列表中的出现次数 .with_columns(count=pl.col("element").count().over(["index", "element"])) # 只保留出现至少两次的元素 .filter(pl.col("count") >= 2) # 按原索引聚合回列表,保持原顺序 .group_by("index", maintain_order=True) .agg(pl.col("element").alias("filtered_lists")) # 右连接原索引,确保所有原始行都被保留(包括无符合条件元素的行) .join(df.select("index"), on="index", how="right") # 把空聚合结果填充为空列表 .fill_null("filtered_lists", []) # 转换为目标Series .select("filtered_lists") .to_series() ) print(result)
输出结果
shape: (3,) Series: 'filtered_lists' [list[i64]] [ [1, 1] [3, 3, 3] [] ]
关键步骤说明
- 转带索引的DataFrame:给每个原始子列表分配唯一索引,确保后续分组能精准对应到原列表。
- explode展开元素:将嵌套列表拆分为每行一个元素的结构,便于统计次数。
- 窗口函数统计次数:通过
over(["index", "element"]),计算每个元素在其所属原列表中的出现次数,避免全局统计干扰。 - 过滤+聚合:筛选出次数达标元素后,按原索引重新聚合成列表,
maintain_order=True保证结果顺序和原Series一致。 - 补全空行:通过右连接和
fill_null处理无符合条件元素的子列表,确保结果行数和原Series完全一致。
内容的提问来源于stack exchange,提问作者ignoring_gravity
相关产品推荐
相关产品推荐

