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

如何动态查询Pandas DataFrame,筛选同时存在于多指定动物园的动物

问题:找出同时出现在指定多个动物园的动物

我有如下结构的Pandas DataFrame:

动物动物园
LionBerlin
LionMunich
LionParis
MonkeyBerlin
MonkeyMunich
MonkeyRotterdam
BatBerlin
GooseRotterdam
TigerParis
TigerMunich

需求是动态构建查询,返回同时出现在指定多个动物园中的唯一动物值,比如找出所有同时在Berlin和Munich动物园的动物,预期结果为:

result = ['Lion', 'Monkey']

我尝试了以下代码:

# 初始化列表
data = [
        ['Lion', 'Berlin'], ['Lion', 'Munich'], ['Lion', 'Paris'],
        ['Monkey', 'Berlin'], ['Monkey', 'Munich'], ['Monkey', 'Rotterdam'],
        ['Bat', 'Berlin'],
        ['Goose', 'Rotterdam'],
        ['Tiger', 'Paris'], ['Tiger', 'Munich']
]
  
# 创建Pandas DataFrame
df = pd.DataFrame(data, columns=['Animal', 'Zoo'])

# 筛选DataFrame
df_filtered = df.query(" (`Zoo` == 'Berlin' | `Zoo` == 'Munich')")

# 将动物转为列表
result = df_filtered['Animal'].unique().tolist()

# 打印结果
print(result)

但该代码返回的是出现在Berlin或Munich动物园的动物,结果为:

['Lion', 'Monkey', 'Bat', 'Tiger']

将逻辑或(|)改为逻辑与(&)后,查询返回空DataFrame:

df.query(" (`Zoo` == 'Berlin' & `Zoo` == 'Munich')")

现寻求正确实现该需求的方法。


解决方案

方法1:分组统计法(推荐,灵活支持任意数量目标动物园)

核心思路是按动物分组,检查每组的动物园集合是否包含所有目标动物园:

import pandas as pd

data = [
        ['Lion', 'Berlin'], ['Lion', 'Munich'], ['Lion', 'Paris'],
        ['Monkey', 'Berlin'], ['Monkey', 'Munich'], ['Monkey', 'Rotterdam'],
        ['Bat', 'Berlin'],
        ['Goose', 'Rotterdam'],
        ['Tiger', 'Paris'], ['Tiger', 'Munich']
]
df = pd.DataFrame(data, columns=['Animal', 'Zoo'])

# 指定目标动物园列表
target_zoos = ['Berlin', 'Munich']

# 分组过滤:保留包含所有目标动物园的动物
result = df.groupby('Animal')['Zoo'].filter(
    lambda x: set(target_zoos).issubset(set(x))
).unique().tolist()

print(result)
# 输出:['Lion', 'Monkey']

方法2:集合交集法

分别获取每个目标动物园的动物集合,再求所有集合的交集:

target_zoos = ['Berlin', 'Munich']

# 生成每个目标动物园对应的动物集合
zoo_animal_sets = [set(df[df['Zoo'] == zoo]['Animal']) for zoo in target_zoos]

# 计算所有集合的交集
result = list(set.intersection(*zoo_animal_sets))

print(result)
# 输出:['Lion', 'Monkey']

方法3:基于query的改进方案

如果偏好使用query,可以先筛选目标动物园的记录,再通过分组计数过滤:

target_zoos = ['Berlin', 'Munich']

# 先筛选出目标动物园的记录
filtered = df.query("Zoo in @target_zoos")

# 保留分组后记录数等于目标动物园数量的动物(即每个目标动物园都有该动物)
result = filtered.groupby('Animal').filter(
    lambda x: len(x) == len(target_zoos)
)['Animal'].unique().tolist()

print(result)
# 输出:['Lion', 'Monkey']

错误原因说明

  • 使用|(逻辑或)时,只要动物出现在任意一个目标动物园就会被选中,因此包含了仅在Berlin的Bat和仅在Munich的Tiger。
  • 使用&(逻辑与)时,要求单条记录同时满足Zoo等于Berlin和Munich,而单条记录只有一个Zoo值,因此不可能成立,返回空DataFrame。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 13:30:34