如何用np.where判断DataFrame中item字符串是否存在于对应mylist列?
用Numpy优化大型DataFrame的逐行列匹配过滤
原代码错误原因
你写的dat[np.where(dat['item'].isin(dat['mylist']), True, False)]逻辑完全错误:
dat['item'].isin(dat['mylist'])会把mylist列的所有列表元素合并成一个全局集合,检查每个item是否在这个全局集合中,而不是检查该行的item是否存在于对应行的mylist里,所以结果全为False。
高效的Numpy/Python优化方案
针对1亿行的大型DataFrame,优先用列表推导式+Numpy布尔索引,速度远快于apply,且实现简单:
方案1:列表推导式生成布尔掩码
import numpy as np import pandas as pd # 示例数据 dat = pd.DataFrame({'ID' : [1,2,3,4,5], 'item' : ['beauty', 'beauty', 'shoe','shoe','handbag'], 'mylist' : [['beauty','something'], ['shoe', 'something', 'else'], ['shoe', 'else','some'], ['else'], ['some', 'thing', 'else']]}) # 生成布尔掩码:逐行检查item是否在对应mylist中 mask = np.array([item in mylist for item, mylist in zip(dat['item'], dat['mylist'])]) # 过滤得到结果 filtered_dat = dat[mask]
方案2:结合集合优化(适合mylist元素较多的场景)
如果mylist里的元素数量较多,把列表转成集合后,in操作的时间复杂度从O(n)降到O(1),能进一步提升速度:
mask = np.array([item in set(mylist) for item, mylist in zip(dat['item'], dat['mylist'])]) filtered_dat = dat[mask]
方案3:Numpy Vectorize(语法更贴近Numpy风格)
如果偏好Numpy的写法,可以用np.vectorize封装检查逻辑,速度和列表推导式接近:
def check_match(item, mylist): return item in mylist # 向量化函数 vectorized_check = np.vectorize(check_match, otypes=[bool]) mask = vectorized_check(dat['item'].values, dat['mylist'].values) filtered_dat = dat[mask]
性能说明
- 列表推导式的速度比
apply快3-5倍左右,对于1亿行的数据集,能大幅缩短运行时间; - 转集合的优化在
mylist长度较大时效果尤为明显; - 避免用
np.where做逐行匹配,它更适合处理全局条件,而非行内的对应关系。
内容的提问来源于stack exchange,提问作者Karthik S
相关产品推荐
相关产品推荐

