何时选择使用pandas的.filter()方法而非其他子集选取方法?
filter 方法的核心定位是仅针对行/列的索引名称做筛选,完全不涉及数据值的校验,这是它和loc、iloc、逻辑筛选等方法最本质的区别,在匹配索引名称的场景下,它的写法比其他方案简洁很多。
先给出示例数据方便对照:
import pandas as pd df = pd.DataFrame({ 'order_id': [1,2,3,4], 'order_date': ['2023-01-01','2023-01-02','2023-01-03','2023-01-04'], 'user_id': [101,102,101,103], 'user_name': ['张三','李四','张三','王五'], 'pay_amount': [99,199,299,399], 'pay_time': ['10:00','11:00','14:00','16:00'] })
场景1:按列名模糊/正则规则批量选列
- 要选取所有名称包含
user的列,filter写法:df.filter(like='user', axis=1)
对比常见替代方案:- 用
loc+str.contains:df.loc[:, df.columns.str.contains('user')] - 用列表推导:
df[[col for col in df.columns if 'user' in col]]
明显filter写法更短、可读性更高。
- 用
如果是正则匹配场景,比如要选所有以_id结尾的列:df.filter(regex='_id$', axis=1)
替代方案需要写df.loc[:, df.columns.str.match('.*_id$')],逻辑更绕。
场景2:精确匹配多列/行,自带容错能力
如果要选取order_id、pay_amount、user_name三列,同时不确定这些列是否都存在于表中,filter不会抛出异常,只会返回存在的列:df.filter(items=['order_id', 'pay_amount', 'user_name', 'not_exist_col'], axis=1)
如果用普通列选取写法df[['order_id', 'pay_amount', 'user_name', 'not_exist_col']],会直接抛出KeyError,在多表合并、批量数据清洗的场景下,filter的容错性可以省去大量列存在性判断的冗余代码。
行索引筛选逻辑一致,比如要选取索引为2023-01-01、2023-01-03、2023-01-05的行,直接写df.filter(items=['2023-01-01','2023-01-03','2023-01-05'], axis=0)即可,不存在的索引会直接忽略。
场景3:多层索引(MultiIndex)下的层级筛选
如果是多层列索引,比如第一层是业务线A、业务线B,第二层是收入、成本、利润,要选所有业务线的利润列,filter写法非常简单:df.filter(like='利润', axis=1, level=1)
如果用loc实现,需要写复杂的元组匹配逻辑,代码复杂度高很多。
不适用场景
filter完全不接触数据值,如果你需要按某列的值筛选(比如选pay_amount>100的行)、或者按位置选取行/列,直接用逻辑运算符、loc、iloc即可,filter不支持这类操作。
内容的提问来源于stack exchange,提问作者S Mann

