
本文介绍如何基于字典映射关系,高效地为 pandas dataframe 添加一列布尔值(true/false),判断每行的 item 是否属于其对应 group 在字典中定义的成员集合。
本文介绍如何基于字典映射关系,高效地为 pandas dataframe 添加一列布尔值(true/false),判断每行的 item 是否属于其对应 group 在字典中定义的成员集合。
在数据处理中,常需根据分组规则动态生成逻辑标记列。给定一个字典 my_dict,其键为组名(如 'Group1'),值为该组包含的项目元组(如 ('Item1', 'Item3')),目标是为 DataFrame 新增一列 'New_col',对每一行判断 df['Item'] 是否属于 df['Group'] 对应字典项中的元素。
最推荐的方法是预构建查找用的字典(映射到集合),以提升查询效率并避免逐行 apply 的性能瓶颈。以下是两种主流策略:
✅ 方案一:正向映射(Group → {Item} 集合)
将原始字典转换为 Group → set(Item) 形式,再通过列表推导式完成逐行判断:
import pandas as pd
my_dict = {
'Group1': ('Item1', 'Item3'),
'Group2': ('Item2', 'Item3', 'Item4', 'Item5'),
'Group3': ('Item1',) # 注意:单元素元组末尾逗号不可省略
}
# 构建 Group → set(Item) 映射
d = {k: set(v) for k, v in my_dict.items()}
df = pd.DataFrame({
'Item': ['Item1', 'Item2', 'Item3', 'Item4'],
'Group': ['Group1', 'Group1', 'Group2', 'Group3']
})
# 添加新列:判断 Item 是否在对应 Group 的集合中
df['New_col'] = [item in d.get(group, set())
for item, group in zip(df['Item'], df['Group'])]
print(df)
输出:
Item Group New_col 0 Item1 Group1 True 1 Item2 Group1 False 2 Item3 Group2 True 3 Item4 Group3 False
⚠️ 注意事项:
- 字典值必须为可迭代对象(如元组、列表),单元素元组需写成 ('Item1',);
- 使用 set() 而非元组/列表进行 in 查询,时间复杂度从 O(n) 降至平均 O(1);
- d.get(group, set()) 确保当 Group 不在字典中时返回空集,避免 KeyError。
✅ 方案二:反向映射(Item → {Group} 集合)
适用于需频繁按 Item 查询所属 Group 的场景,构建 Item → set(Group) 映射后反查:
# 构建 Item → set(Group) 映射
d_reverse = {}
for group, items in my_dict.items():
for item in items:
d_reverse.setdefault(item, set()).add(group)
# 判断当前 Group 是否在该 Item 对应的 Group 集合中
df['New_col'] = [group in d_reverse.get(item, set())
for item, group in zip(df['Item'], df['Group'])]
该方案逻辑等价,但更适合后续扩展(如统计某 Item 属于几个 Group)。
? 扩展:支持子串匹配(模糊匹配)
若 Item 列含变体(如 'Item1a'、'Item2bc'),需先提取基础项再匹配,可结合正则实现:
import re
# 提取所有可能的 Item 根名称(去重 + 转义)
all_items = {item for items in my_dict.values() for item in items}
pattern = '|'.join(map(re.escape, all_items)) # 如 'Item1|Item2|Item3|Item4|Item5'
# 从 'Item' 列中提取首个匹配的基础项
extracted = df['Item'].str.extract(f'({pattern})', expand=False)
# 基于提取结果做正向映射判断
df['New_col'] = [item in d.get(group, set())
for item, group in zip(extracted, df['Group'])]
例如输入 ['Item1a', 'Item2bc', 'Item3a', 'Item4ad'],仍可正确识别并标记为 [True, False, True, False]。
✅ 总结:优先采用正向集合映射 + 列表推导方式,简洁、高效、易读;避免使用 apply() 或 str.startswith() 等低效或语义不符的操作;对于模糊匹配需求,配合正则预处理即可灵活扩展。











