pandas如何根据列表类型单元格含指定字符串的条件删除行
问题场景
处理pandas DataFrame时,jpgs列的单元格值均为列表类型,需要删除该列列表中包含字符串"123.jpg"的所有行,最终仅保留原索引为1、3的行。
错误写法原因分析
之前几种写法报错或结果不符合预期,核心原因都是没有生成逐行判断的布尔筛选序列:
- 执行
df = df["123.jpg" not in df.jpgs]、df = df.drop(df["123.jpg" in df.jpgs].index)抛出KeyError: True/False:in关键字是直接对df.jpgs这个Series对象做整体成员判断,只会返回单个布尔值(True或False),pandas会把这个布尔值当做列名去查找对应列,自然找不到抛出KeyError。 - 执行
df = df[df.jpgs.tolist().count("123.jpg") == 0]触发KeyError:df.jpgs.tolist()会把整列转成嵌套列表,对这个嵌套列表直接count"123.jpg"结果永远是0,最终得到的也是单个布尔值True,同样会被当做列名索引触发KeyError。 - 执行
df = df[df['jpgs'].str.contains('123.jpg') == False]返回空DataFrame:.str是pandas提供的字符串类型专属访问器,仅当单元格值为字符串时才能正常工作,当前单元格存储的是列表,调用.str.contains时所有行都会返回空值NaN,和False做相等判断后结果全为False,筛选后自然是空表。
正确实现方案
两种常用写法均可实现需求,数据量较大时优先选第二种,运行速度更快:
- apply逐行判断写法
# 波浪号表示取反,即保留"123.jpg"不在列表中的行 df = df[~df['jpgs'].apply(lambda x: "123.jpg" in x)]
- 列表推导式写法(性能更优)
df = df[["123.jpg" not in item for item in df['jpgs']]]
完整可运行测试代码
注意pandas 2.0及以上版本已经弃用df.append()方法,这里替换为官方推荐的pd.concat()实现:
import pandas as pd # 初始化数据 df = pd.DataFrame(columns=["person_id", "jpgs"]) pair1 = ["123.jpg", "124.jpg"] pair2 = ["125.jpg", "300.jpg"] pair3 = ["500.jpg", "123.jpg"] pair4 = ["111.jpg", "122.jpg"] rows = [ {'person_id': 1, 'jpgs': pair1}, {'person_id': 1, 'jpgs': pair2}, {'person_id': 1, 'jpgs': pair3}, {'person_id': 1, 'jpgs': pair4} ] df = pd.concat([df, pd.DataFrame(rows)], ignore_index=True) print("原始数据:") print(df) # 执行筛选 df = df[["123.jpg" not in item for item in df['jpgs']]] print("\n筛选后结果:") print(df)
运行后输出结果符合预期,仅保留jpgs列表不含123.jpg的两行数据。
内容的提问来源于stack exchange,提问作者meh.pandalala
相关产品推荐
相关产品推荐

