如何遍历DataFrame并根据邮箱前缀提取子串生成新列
解决DataFrame逐行提取group_code的问题
原代码的核心问题是:str.startswith返回的是布尔值Series,直接和True比较会导致整个条件判断为False,无法逐行匹配规则。以下是几种可行的修改方案:
方案1:使用apply逐行处理
自定义处理单个邮箱的函数,通过apply对group_email列逐行执行逻辑:
import pandas as pd import numpy as np def extract_group_code(email): email_str = str(email) if email_str.startswith("gcp"): match = pd.Series(email_str).str.extract('(?:prod-)(.*)-')[0].iloc[0] return match if pd.notna(match) else np.nan elif email_str.startswith("irm"): match = pd.Series(email_str).str.extract('^(?:[^-]*\-){6}([^.]*)')[0].iloc[0] return match if pd.notna(match) else np.nan else: return np.nan group_member_df['group_code'] = group_member_df['group_email'].apply(extract_group_code)
方案2:使用np.where嵌套实现向量化判断
利用numpy的向量化操作替代逐行循环,效率更高(适合大数据量):
import pandas as pd import numpy as np # 先标记各行的匹配类型 is_gcp = group_member_df['group_email'].astype(str).str.startswith("gcp") is_irm = group_member_df['group_email'].astype(str).str.startswith("irm") # 提取gcp对应的code gcp_codes = group_member_df.loc[is_gcp, 'group_email'].str.extract('(?:prod-)(.*)-')[0] # 提取irm对应的code irm_codes = group_member_df.loc[is_irm, 'group_email'].str.extract('^(?:[^-]*\-){6}([^.]*)')[0] # 嵌套where赋值 group_member_df['group_code'] = np.where( is_gcp, gcp_codes, np.where( is_irm, irm_codes, np.nan ) )
方案3:直接通过mask批量赋值
先初始化group_code为NaN,再分别给符合条件的行赋值:
import pandas as pd import numpy as np group_member_df['group_code'] = np.nan # 处理gcp开头的行 gcp_mask = group_member_df['group_email'].astype(str).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'].astype(str).str.startswith("irm") group_member_df.loc[irm_mask, 'group_code'] = group_member_df.loc[irm_mask, 'group_email'].str.extract('^(?:[^-]*\-){6}([^.]*)')[0]
注意事项
- 原代码中使用字符串
"null"表示空值,建议改用pandas标准的np.nan,便于后续空值处理(如dropna()、fillna())。 str.extract返回的是DataFrame,取[0]是提取第一个捕获组的结果(即括号内匹配的内容)。
内容的提问来源于stack exchange,提问作者unnest_me
相关产品推荐
相关产品推荐

