You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Series的索引与值动态过滤Pandas DataFrame?

用Series动态匹配列名和值过滤Pandas DataFrame

问题场景

给定如下示例代码,需要筛选出DataFrame中与Series索引(对应DataFrame列名)和值完全匹配的行:

import pandas as pd
filter_ = pd.Series(
    data = [1, 9, 10],
    index = ['A', 'B', 'C']
)
filter_.index.name = 'my_id'

df = pd.DataFrame({
    'A': [1, 2, 9, 4],
    'B': [9, 6, 7, 8],
    'C': [10, 91, 32, 13],
    'D': [43, 12, 7, 9],
    'E': [65, 12, 3, 8]
})

期望结果:

A   B   C   D   E
0   1   9   10  43  65

已知限制:

  • .query()方法因数据中存在pathlib对象无法使用
  • 单条件过滤(如df.loc[df[filter.index[0]] == filter.iloc[0]])可行,但需要实现动态多条件匹配
  • 部分方案在数据含None值时会失效,需兼容该场景

解决方案

1. 动态构建布尔掩码(兼容None值)

遍历Series的键值对,根据值是否为None选择对应的判断逻辑,逐步叠加布尔条件:

mask = pd.Series([True] * len(df), index=df.index)
for col, val in filter_.items():
    if pd.isna(val):
        mask &= df[col].isna()
    else:
        mask &= df[col] == val

result = df[mask]

该方法逻辑直观,能兼容None值场景,适合中等规模数据集。

2. 逐行apply判断(小数据集最优)

通过apply逐行验证是否匹配所有过滤条件,代码简洁,小数据集下性能最快:

def match_row(row):
    for col, val in filter_.items():
        if pd.isna(val):
            if not pd.isna(row[col]):
                return False
        else:
            if row[col] != val:
                return False
    return True

result = df[df.apply(match_row, axis=1)]

3. 分非空/空列矢量化处理(大数据集最优)

拆分非空和空列的过滤逻辑,利用Pandas矢量化操作提升性能,大数据集下表现最优:

# 拆分过滤条件为非空和空列两部分
non_null_filter = filter_.dropna()
null_cols = filter_[filter_.isna()].index

# 非空列全匹配
mask = df[non_null_filter.index].eq(non_null_filter).all(axis=1)
# 空列全为NaN的匹配(如果有空列条件)
if not null_cols.empty:
    mask &= df[null_cols].isna().all(axis=1)

result = df[mask]

该方法避免了逐行循环,充分利用Pandas的底层优化,数据量越大性能优势越明显。


性能对比

通过%%timeit测试验证:

  • 小数据集:apply()方法最快
  • 大数据集:分非空/空列处理的方法性能最优

内容的提问来源于stack exchange,提问作者Luke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 16:15:13