
本文介绍如何基于字典映射关系,高效地为 pandas dataframe 添加一个布尔型新列(true/false),判断每行的 item 是否属于其对应 group 在字典中定义的成员集合。
本文介绍如何基于字典映射关系,高效地为 pandas dataframe 添加一个布尔型新列(true/false),判断每行的 item 是否属于其对应 group 在字典中定义的成员集合。
在数据处理中,常需依据预定义的分组规则(如字典)对 DataFrame 行进行逻辑校验,并生成对应的布尔标记列。核心挑战在于:避免逐行 apply 的低效操作,同时正确处理键值匹配逻辑。下面提供两种主流且高效的解决方案——直接映射与反向映射,并附带扩展用法。
✅ 方案一:直接映射(推荐,简洁高效)
将原始字典 my_dict 转换为 {Group: set(items)} 结构,再通过列表推导式完成 O(1) 成员检查:
import pandas as pd
my_dict = {
'Group1': ('Item1', 'Item3'),
'Group2': ('Item2', 'Item3', 'Item4', 'Item5'),
'Group3': ('Item1',) # 注意:单元素元组必须加逗号
}
# 构建 Group → 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']
})
# 添加新列:判断 df['Item'] 是否在对应 df['Group'] 的允许集合中
df['New_col'] = [item in d.get(group, set())
for item, group in zip(df['Item'], df['Group'])]
✅ 优势:逻辑清晰、执行快(无 lambda + apply 嵌套)、内存友好。
⚠️ 注意:d.get(group, set()) 确保当 Group 不在字典中时返回空集,避免 KeyError,结果自然为 False。
✅ 方案二:反向映射(适用于多对一查询场景)
若后续还需支持“某 Item 属于哪些 Groups”,可构建 {Item: set(groups)} 映射:
d_reverse = {}
for group, items in my_dict.items():
for item in items:
d_reverse.setdefault(item, set()).add(group)
# 判断当前 Group 是否包含当前 Item
df['New_col'] = [group in d_reverse.get(item, set())
for item, group in zip(df['Item'], df['Group'])]
该方式在需频繁按 Item 反查 Group 时更具扩展性,但本例中性能略低于方案一。
? 扩展:支持子串匹配(模糊匹配)
若 Item 列含变体(如 'Item1a', 'Item3b'),需先提取基础项再匹配,可结合正则:
import re
# 提取所有可能的基础项(去重并转义)
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'
# 提取最左匹配的基础项
base_item = df['Item'].str.extract(f'({pattern})', expand=False)
# 使用方案一的映射逻辑
df['New_col'] = [item in d.get(group, set())
for item, group in zip(base_item, df['Group'])]
? 示例输入 'Item1a' → 提取 'Item1' → 查 d['Group1'] → True
? 总结
- 避免 df['col'].apply(lambda x: ...) 嵌套调用,易触发 TypeError: expected a string or tuple, not Series;
- 优先使用集合(set)而非元组/列表,显著提升 in 操作性能;
- 单元素元组务必写成 ('Item1',),否则 'Item1' 是字符串,非元组;
- 生产环境建议封装为函数,增强复用性与可读性:
def add_membership_col(df, item_col, group_col, mapping_dict, new_col):
d = {k: set(v) for k, v in mapping_dict.items()}
df[new_col] = [item in d.get(group, set())
for item, group in zip(df[item_col], df[group_col])]
return df
df = add_membership_col(df, 'Item', 'Group', my_dict, 'New_col')
至此,你已掌握基于字典动态添加布尔列的核心技巧——兼顾正确性、性能与可维护性。











