将str.extract提取值赋值给DataFrame列时出现异常行为
问题原因与解决方法
核心原因:索引对齐机制导致的赋值失败
你遇到的NaN问题本质是Pandas的索引对齐规则在起作用:
df.Cypher.str.extract('(.*)/(.*)')返回的是和原DataFrame行数完全一致的新DataFrame,其中不包含/的行全部为NaN。- 而
df.loc[df.Cypher.str.contains('/'), ['Cypher', 'Bass']]选取的是原DataFrame中仅含/的子集行,它的索引只是原索引的一部分。 - 当你试图把全量的extract结果赋值给这个子集时,Pandas会严格按索引对齐:extract结果中,只有与.loc子集索引完全匹配的行才有有效值,但赋值操作会尝试将整个extract的DataFrame映射到目标子集,由于两者的索引范围不一致,最终导致目标列被覆盖为NaN。
正确的赋值方式
方法1:先过滤提取结果再赋值
先把extract的结果过滤出有效行(即不含NaN的行),再通过索引匹配赋值:
# 提取并过滤出匹配成功的行 extracted = df.Cypher.str.extract('(.*)/(.*)').dropna() # 按索引匹配,更新Cypher列和Bass列 df.loc[extracted.index, 'Cypher'] = extracted[0] df.loc[extracted.index, 'Bass'] = extracted[1]
方法2:先全量赋值再还原未匹配的Cypher值
如果你的Bass列原本不存在,可以先全量赋值,再用原Cypher值还原未匹配的行:
# 备份原Cypher列 df['_temp_cypher'] = df['Cypher'] # 全量提取赋值 df[['Cypher', 'Bass']] = df.Cypher.str.extract('(.*)/(.*)') # 用备份的原数据填充Cypher列的NaN(即未匹配/的行) df['Cypher'] = df['Cypher'].combine_first(df['_temp_cypher']) # 删除临时列 df.drop('_temp_cypher', axis=1, inplace=True)
内容的提问来源于stack exchange,提问作者Federico
相关产品推荐
相关产品推荐

