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

如何在Pandas中实现spec列与对应行lst列列表的匹配(广播.isin)

Pandas:逐行检查值是否存在于对应行的列表中

在匹配spec与允许值的工作流中,我需要找出哪些行符合spec要求——即每行的spec值是否存在于该行的lst列表里。这和Stack Overflow上《Pandas, isin, column of lists》的问题不同,因为我不是将每行与一个静态列表匹配。

我试过用.explode+.groupby或者.apply实现需求:前者操作过于繁琐,后者存在性能问题。我认为应该有更优的实现方式,但不知道该怎么做——尝试让.isin实现广播却没成功,这原本看起来是最佳解决方案。


示例代码

import pandas as pd
import numpy as np

df = pd.DataFrame(data = {
    'name': ['a', 'b', 'c'],
    'lst': [[0,2,4], [1,2], []],
    'spec': [2,4,0]
})
expect = pd.DataFrame(data= {
    'name': ['a', 'b', 'c'],
    'match_spec': [True, False, False] 
})

def check(f):
  try:
    got = f()
    result = (expect['match_spec'] == got)
    ok = result.all()
    if ok:
      print(f'OK {f}')
    else:
      print(f'FAIL {f}\n{got}')
  except Exception as ex:
    print(f'ERROR {f}\n{ex}')

# 尝试的方法
def naive_broadcast(): return df.spec in df.lst
check(naive_broadcast)

def result_apply(): return df.apply(lambda x: x.spec in x.lst, axis=1)
check(result_apply)

def naive_isin(): return df.spec.isin(df.lst)
check(naive_isin)

def vectorization(): np.vectorize(df.spec.isin)(df.lst.values)
check(vectorization)

# 繁琐的方法:explode+groupby
def explode_groupby():
  exp = df.explode('lst')
  return (exp.assign(m = (exp['lst'].eq(exp['spec'])))
    .groupby('name')
    .agg(match_spec=('m', max))
    .reset_index()['match_spec'])
check(explode_groupby)

尝试结果

ERROR <function naive_broadcast at 0x7fe0a4f6c9d0>
不可哈希类型: 'Series'
OK <function result_apply at 0x7fe0a4f6ca60>
FAIL <function naive_isin at 0x7fe0a4f6c310>
0    False
1    False
2    False
Name: spec, dtype: bool
ERROR <function vectorization at 0x7fe0a4f6c940>
使用序列设置数组元素。
OK <function explode_groupby at 0x7fe0a4f6ce50>

最优实现方案

1. 列表推导式(推荐,性能最优)

列表推导式是纯Python循环,比df.apply的开销小很多,代码简洁且高效:

df['match_spec'] = [spec in lst for spec, lst in zip(df['spec'], df['lst'])]
# 验证结果
print(df['match_spec'].equals(expect['match_spec']))  # 输出 True

2. 正确使用np.vectorize

如果偏好向量化写法,可以用np.vectorize包装逐元素检查的函数,注意要传入正确的元素级函数:

def check_spec_in_lst(spec, lst):
    return spec in lst

vec_check = np.vectorize(check_spec_in_lst)
df['match_spec'] = vec_check(df['spec'], df['lst'])
# 验证结果
print(df['match_spec'].equals(expect['match_spec']))  # 输出 True

失败原因说明

  • naive_broadcast:df.spec in df.lst是将整个spec Series与lst Series比较,不是逐行匹配,因此报错“不可哈希类型: 'Series'”。
  • naive_isin:df.spec.isin(df.lst)的逻辑是检查每个spec值是否存在于所有行的lst列表合并后的集合中,而非当前行的lst列表,因此全部返回False。
  • vectorization:写法错误,np.vectorize需要传入元素级的函数,而不是直接传入df.spec.isin这种Series方法,导致类型不匹配报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 02:00:38