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

如何在pandas.query()中使用字典作为多条件进行过滤?

解决办法

报错原因

query()中直接使用@workers[person]会触发TypeError: unhashable type: 'Series',因为person是DataFrame的列(Series类型),而字典的键必须是可哈希的标量值,无法直接用Series作为键去索引字典。

方案一:用apply()逐行校验

逻辑直观,适合小数据量场景:

import pandas as pd
import datetime as dt

# 初始化数据
workers = {
    'Alan': [dt.date(2017, 1, 15), dt.date(2020, 5, 4)],
    'Ben': [dt.date(2018, 3, 28), dt.date(2021, 5, 7)]
}

df = pd.DataFrame({
    'event_id': ['1LFDVDX', '4DLDQVC', '5PEXVGH', '9OPCLXD'],
    'person': ['Alan', 'Ben', 'Ben', 'John'],
    'event_date': pd.to_datetime(['2018-10-28', '2022-02-01', '2019-09-05', '2020-06-15']).dt.date
})

# 生成过滤掩码
mask = df.apply(
    lambda row: row['person'] in workers 
    and workers[row['person']][0] <= row['event_date'] <= workers[row['person']][1],
    axis=1
)
result = df[mask]
print(result)

输出结果:

event_id person  event_date
0  1LFDVDX   Alan  2018-10-28
2  5PEXVGH    Ben  2019-09-05

方案二:字典转DataFrame合并过滤

性能更优,适合大数据量场景:

# 将workers字典转为区间DataFrame
worker_ranges = pd.DataFrame.from_dict(
    workers, 
    orient='index', 
    columns=['start_date', 'end_date']
).reset_index().rename(columns={'index': 'person'})

# 合并原数据与区间数据,仅保留匹配的员工
merged_df = df.merge(worker_ranges, on='person', how='inner')

# 过滤日期在区间内的记录
result = merged_df[
    (merged_df['event_date'] >= merged_df['start_date']) 
    & (merged_df['event_date'] <= merged_df['end_date'])
][['event_id', 'person', 'event_date']]
print(result)

方案三:改造query()写法

如果坚持使用query(),可以先通过映射生成区间列,再执行过滤:

# 为原数据添加员工对应的起止日期列
df['start_date'] = df['person'].map(lambda x: workers.get(x, [None, None])[0])
df['end_date'] = df['person'].map(lambda x: workers.get(x, [None, None])[1])

# 用query执行过滤
result = df.query(
    'person in @workers and event_date >= start_date and event_date <= end_date'
)[['event_id', 'person', 'event_date']]
print(result)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 15:48:29