如何遍历Pandas DataFrame按条件从group_email生成group_code
解决Pandas逐行解析group_email生成group_code的问题
你的原代码无法逐行处理的核心原因是:group_member_df['group_email'].str.startswith("gcp")返回的是布尔值Series(每行对应一个True/False),直接和is True比较会把整个Series转换成单个布尔值(判断所有元素是否全为True),导致逻辑只执行一次,无法覆盖逐行的分支判断。
下面提供几种高效的修正方案:
方案1:向量化判断(推荐,大数据量友好)
利用numpy.where实现嵌套条件赋值,结合Pandas的字符串方法完成批量提取,效率远高于逐行循环:
import numpy as np import pandas as pd # 预先提取两种规则下的结果(expand=False返回Series,避免生成DataFrame) gcp_result = group_member_df['group_email'].str.extract(r'(?:prod-)(.*)-', expand=False) irm_result = group_member_df['group_email'].str.extract(r'^(?:[^-]*\-){6}([^.]*)', expand=False) # 按条件逐行赋值 group_member_df['group_code'] = np.where( group_member_df['group_email'].str.startswith('gcp'), gcp_result, np.where( group_member_df['group_email'].str.startswith('irm'), irm_result, 'null' ) ) # 处理正则匹配失败导致的NaN值,统一替换为'null' group_member_df['group_code'] = group_member_df['group_code'].fillna('null')
方案2:逐行apply处理(小数据量直观)
如果数据量不大,用apply定义单行处理逻辑更易理解:
def parse_group_code(email): email_str = str(email) if email_str.startswith('gcp'): match = pd.Series(email_str).str.extract(r'(?:prod-)(.*)-', expand=False)[0] return match if pd.notna(match) else 'null' elif email_str.startswith('irm'): match = pd.Series(email_str).str.extract(r'^(?:[^-]*\-){6}([^.]*)', expand=False)[0] return match if pd.notna(match) else 'null' else: return 'null' group_member_df['group_code'] = group_member_df['group_email'].apply(parse_group_code)
方案3:布尔掩码分步赋值
通过布尔掩码定位不同条件的行,分步完成赋值,逻辑清晰:
# 初始化所有行为'null' group_member_df['group_code'] = 'null' # 处理gcp开头的行 mask_gcp = group_member_df['group_email'].str.startswith('gcp') group_member_df.loc[mask_gcp, 'group_code'] = group_member_df.loc[mask_gcp, 'group_email'].str.extract(r'(?:prod-)(.*)-', expand=False) # 处理irm开头的行 mask_irm = group_member_df['group_email'].str.startswith('irm') group_member_df.loc[mask_irm, 'group_code'] = group_member_df.loc[mask_irm, 'group_email'].str.extract(r'^(?:[^-]*\-){6}([^.]*)', expand=False) # 替换匹配失败的NaN值 group_member_df['group_code'] = group_member_df['group_code'].fillna('null')
针对你提供的示例数据,所有group_email均以gcp开头,正则(?:prod-)(.*)-会从gcp-edp-platform-dgov-prod-aadrpt-allsensitive.groups@ironmountain.com中提取出aadrpt,最终所有行的group_code都会被设置为aadrpt。
内容的提问来源于stack exchange,提问作者unnest_me
相关产品推荐
相关产品推荐

