DataFrame迭代提取列子串遇AttributeError,求正确实现方法
解决DataFrame中按邮箱前缀提取子串的AttributeError问题
我有一个包含多列的DataFrame,需要从group_email列提取特定子串生成新列group_code。邮箱遵循多种格式,需先判断开头前缀,再使用对应正则表达式提取。
原实现代码
for ind in group_member_df.index: if(group_member_df['group_email'][ind].startswith("gcp") is True): group_member_df['group_code'][ind] = (group_member_df['group_email'][ind].str.extract('(?:prod-)(.*)-')) elif(group_member_df['group_email'][ind].startswith("irm") is True): group_member_df['group_code'][ind] = (group_member_df['group_email'][ind].str.extract('^(?:[^-]*\-){6}([^.]*)')) else: group_member_df['group_code'][ind] = '0'
报错信息
Traceback (most recent call last): File "directory.py", line 225, in <module> main(sys.argv[1:]) File "directory.py", line 202, in main group_member_df['group_code'][ind] = (group_member_df['group_email'][ind].str.extract('(?:prod-)(.*)-')) AttributeError: 'str' object has no attribute 'str'
错误原因
group_member_df['group_email'][ind]取到的是单个字符串值,而.str是Pandas Series专属属性,无法直接作用于单个字符串。- 循环遍历DataFrame索引的方式效率低下,违背Pandas向量化操作的设计原则。
正确实现方式
方法一:向量化批量处理(推荐)
利用Pandas的布尔掩码和字符串方法批量操作,效率远高于循环:
# 初始化group_code列为默认值'0' group_member_df['group_code'] = '0' # 筛选gcp开头的邮箱,提取目标子串 gcp_mask = group_member_df['group_email'].str.startswith('gcp') group_member_df.loc[gcp_mask, 'group_code'] = group_member_df.loc[gcp_mask, 'group_email'].str.extract('(?:prod-)(.*)-')[0] # 筛选irm开头的邮箱,提取目标子串 irm_mask = group_member_df['group_email'].str.startswith('irm') group_member_df.loc[irm_mask, 'group_code'] = group_member_df.loc[irm_mask, 'group_email'].str.extract('^(?:[^-]*\-){6}([^.]*)')[0]
说明:
.str.extract返回DataFrame,取[0]提取第一列的Series值,直接赋值给目标列。- 布尔掩码精准筛选目标行,避免不必要的计算。
方法二:修正循环实现(不推荐,仅作参考)
若必须使用循环,改用Python标准正则库处理单个字符串:
import re group_member_df['group_code'] = '0' for ind in group_member_df.index: email = group_member_df['group_email'][ind] if email.startswith('gcp'): match = re.search(r'(?:prod-)(.*)-', email) if match: group_member_df.loc[ind, 'group_code'] = match.group(1) elif email.startswith('irm'): match = re.search(r'^(?:[^-]*\-){6}([^.]*)', email) if match: group_member_df.loc[ind, 'group_code'] = match.group(1)
说明:
- 用
re.search处理单个字符串,匹配成功后通过group(1)获取捕获组内容。 - 使用
df.loc[ind, 'col']赋值,避免链式索引引发的SettingWithCopyWarning。
测试验证
针对你提供的测试数据,使用推荐方法处理后,group_code列会提取出aadrpt(对应gcp开头邮箱中的目标子串)。
内容的提问来源于stack exchange,提问作者unnest_me
相关产品推荐
相关产品推荐

