如何在两个Pandas DataFrame中对应重命名重复的RELEVE_NR
解决方案:修复重复样地ID并同步物种数据
步骤1:处理df_header的重复RELEVE_NR,生成唯一ID
先标记df_header中每个重复ID的出现顺序,为非首次出现的行分配未使用的新ID,同时记录旧ID到新ID的映射关系:
import pandas as pd # 获取当前最大的样地ID,作为新ID的起始值 max_existing_id = df_header['RELEVE_NR'].max() next_new_id = max_existing_id + 1 # 标记每个ID在组内的出现顺序(0为首次出现) df_header['duplicate_rank'] = df_header.groupby('RELEVE_NR').cumcount() # 构建旧ID+出现顺序到新ID的映射 id_mapping = {} for idx, row in df_header.iterrows(): old_id = row['RELEVE_NR'] rank = row['duplicate_rank'] if rank == 0: # 首次出现的ID保留原值 id_mapping[(old_id, rank)] = old_id else: # 重复项分配新ID,每次递增 id_mapping[(old_id, rank)] = next_new_id next_new_id += 1 # 更新df_header的RELEVE_NR列 df_header['RELEVE_NR'] = df_header.apply( lambda x: id_mapping[(x['RELEVE_NR'], x['duplicate_rank'])], axis=1 ) # 删除临时辅助列 df_header.drop('duplicate_rank', axis=1, inplace=True)
步骤2:同步更新df_species的物种数据
根据步骤1生成的映射,将对应重复ID的物种行复制,并替换为新的样地ID:
# 整理映射:将旧ID对应到所有关联的新ID列表 old_to_new_ids = {} for (old_id, _), new_id in id_mapping.items(): if old_id not in old_to_new_ids: old_to_new_ids[old_id] = [] old_to_new_ids[old_id].append(new_id) # 生成更新后的物种数据 new_species_rows = [] for idx, row in df_species.iterrows(): old_id = row['RELEVE_NR'] # 获取当前旧ID对应的所有新ID(无重复则仅原ID) target_ids = old_to_new_ids.get(old_id, [old_id]) # 为每个目标ID复制一行并替换ID for new_id in target_ids: updated_row = row.copy() updated_row['RELEVE_NR'] = new_id new_species_rows.append(updated_row) # 转换为DataFrame df_species_updated = pd.DataFrame(new_species_rows)
验证结果
可以通过以下代码确认处理是否正确:
# 检查df_header的ID是否完全唯一 assert df_header['RELEVE_NR'].nunique() == len(df_header), "df_header仍存在重复ID" # 检查每个新ID对应的物种数量是否与原ID一致 for old_id, new_ids in old_to_new_ids.items(): original_count = len(df_species[df_species['RELEVE_NR'] == old_id]) for new_id in new_ids: assert len(df_species_updated[df_species_updated['RELEVE_NR'] == new_id]) == original_count, \ f"新ID {new_id} 的物种行数与原ID {old_id} 不匹配"
内容的提问来源于stack exchange,提问作者César Leblanc
相关产品推荐
相关产品推荐

