Pandas提取候选人姓氏异常:str.get()未正确处理含Jr.的姓名
问题分析与解决方法
错误原因
你写的names函数逻辑是对整个DataFrame列做全局判断,而非针对每一行的姓名单独处理。比如如果你的代码是判断整个列是否所有姓名都含"Jr.",只要有一个姓名不含该后缀,所有行都会走else分支——而含"Jr."的姓名拆分后,倒数第二个元素才是姓氏,倒数第一个是"Jr.",所以会错误提取出"Jr."。
解决方法
方法一:逐行判断的矢量化实现
用np.where结合字符串判断,针对每一行姓名单独处理,逻辑清晰直接:
import numpy as np import pandas as pd # 示例DataFrame df = pd.DataFrame({ 'Candidate_Name': ['Herman West Jr.', 'John A. Smith', 'Robert Lee', 'Mike Brown Jr.'] }) # 拆分姓名为单词列表(正则处理多个空格的情况) name_parts = df['Candidate_Name'].str.split(r'\s+') # 逐行判断:含"Jr."则取倒数第二个单词,否则取倒数第一个 df['Last_Name'] = np.where( df['Candidate_Name'].str.contains(r'\bJr\.', case=False), # \b确保匹配独立的"Jr.",兼容大小写 name_parts.str.get(-2), name_parts.str.get(-1) )
运行后输出结果:
| Candidate_Name | Last_Name |
|---|---|
| Herman West Jr. | West |
| John A. Smith | Smith |
| Robert Lee | Lee |
| Mike Brown Jr. | Brown |
方法二:正则提取(更鲁棒,支持多种后缀)
如果还需要处理Sr.、III、II等其他后缀,用正则提取更灵活:
import re # 第一步:提取带后缀的姓名中的姓氏 df['Last_Name'] = df['Candidate_Name'].str.extract( r'(\w+)\s+(?:Jr\.|Sr\.|III|II)$', expand=False, flags=re.IGNORECASE # 忽略大小写 ) # 第二步:填充不带后缀的姓名的姓氏(取最后一个单词) df['Last_Name'] = df['Last_Name'].fillna( df['Candidate_Name'].str.extract(r'(\w+)$', expand=False) )
这个方法能覆盖更多姓名后缀场景,避免索引取值的局限性。
额外注意事项
- 如果姓名中有多个连续空格,用
str.split(r'\s+')代替默认的str.split(),确保拆分结果准确 - 若存在连字符姓氏(如
Anna Lee-Smith),需要调整正则或拆分逻辑,比如先按空格拆分,再检查最后一个元素是否包含连字符
内容的提问来源于stack exchange,提问作者Damon C. Roberts
相关产品推荐
相关产品推荐

