如何在不同索引下基于条件从另一DataFrame更新pandas DataFrame行?
问题描述
我有两个示例数据集:
test1
ID Label Key 0 K1a89aKkkkkk 23 23_TAMPA 1 Ka18d8Kkkkkk 2 2_MIAMI 2 Kae851Kkkkkk 10 10_WEST PALM BEACH 3 Kf054cKkkkkk 27 27_JACKSONVILLE 4 Ka1129Kkkkkk 2 2_MIAMI 5 Kae8e1Kkkkkk 10 10_WEST PALM BEACH 6 Ka9045Kkkkkk 50 50_ORLANDO 7 K1a95eKkkkkk 51 51_SAINT PETERSBURG 8 Kae931Kkkkkk 19 19_FORT LAUDERDALE 9 Ka1382Kkkkkk 19 19_FORT LAUDERDALE
test2
ID Label Key 9791 Ke53a3Kkkkkk NaN NaN 9792 Ke1c8dKkkkkk NaN NaN 9793 Kf69acKkkkkk NaN NaN 9794 Ke2821Kkkkkk NaN NaN 9795 Ke0a14Kkkkkk NaN NaN 9796 Kf6a4cKkkkkk NaN NaN 9797 Ka83acKkkkkk NaN NaN 9798 Kf4698Kkkkkk NaN NaN 9799 Ke1981Kkkkkk NaN NaN 9800 Ka9a40Kkkkkk NaN NaN
我想基于test1的条件更新test2的Label和Key列,比如当test2中ID为Ke2821Kkkkkk时,把它的Label和Key更新为2和2_MIAMI。
我尝试了以下代码:
test2.loc[test2["ID"]=="Ke2821Kkkkkk"][["Label", "Key"]] = test1.loc[test1["ID"]=="Ka1129Kkkkkk"][["Label", "Key"]] test2.loc[test2["ID"]=="Ka83acKkkkkk"][["Label", "Key"]] = test1.loc[test1["ID"]=="Ka9045Kkkkkk"][["Label", "Key"]] test2.loc[test2["ID"]=="Ka9a40Kkkkkk"][["Label", "Key"]] = test1.loc[test1["ID"]=="Ka1129Kkkkkk"][["Label", "Key"]]
但因为两个DataFrame的索引不同,更新操作没生效。请问怎么在不同索引下,基于条件从另一个DataFrame更新目标DataFrame的行?
期望输出:
ID Label Key 9791 Ke53a3Kkkkkk NaN NaN 9792 Ke1c8dKkkkkk NaN NaN 9793 Kf69acKkkkkk NaN NaN 9794 Ke2821Kkkkkk 2 2_MIAMI 9795 Ke0a14Kkkkkk NaN NaN 9796 Kf6a4cKkkkkk NaN NaN 9797 Ka83acKkkkkk 50 50_ORLANDO 9798 Kf4698Kkkkkk NaN NaN 9799 Ke1981Kkkkkk NaN NaN 9800 Ka9a40Kkkkkk 2 2_MIAMI
解决方案
方法1:提取值时忽略索引(直接用.values)
代码失效的核心原因是赋值时保留了test1的索引,导致和test2的索引不匹配。可以通过.values提取纯数值数组来忽略索引,直接完成赋值:
# 更新Ke2821Kkkkkk mask = test2["ID"] == "Ke2821Kkkkkk" test2.loc[mask, ["Label", "Key"]] = test1.loc[test1["ID"] == "Ka1129Kkkkkk", ["Label", "Key"]].values # 更新Ka83acKkkkkk mask = test2["ID"] == "Ka83acKkkkkk" test2.loc[mask, ["Label", "Key"]] = test1.loc[test1["ID"] == "Ka9045Kkkkkk", ["Label", "Key"]].values # 更新Ka9a40Kkkkkk mask = test2["ID"] == "Ka9a40Kkkkkk" test2.loc[mask, ["Label", "Key"]] = test1.loc[test1["ID"] == "Ka1129Kkkkkk", ["Label", "Key"]].values
方法2:构造映射字典批量更新(更高效)
如果需要更新的条目较多,建议先从test1构建ID到(Label, Key)的映射,再批量更新test2,代码更简洁易维护:
# 从test1创建ID到Label和Key的映射 id_map = test1.set_index("ID")[["Label", "Key"]] # 定义test2需要更新的ID与test1对应ID的关系 update_pairs = { "Ke2821Kkkkkk": "Ka1129Kkkkkk", "Ka83acKkkkkk": "Ka9045Kkkkkk", "Ka9a40Kkkkkk": "Ka1129Kkkkkk" } # 遍历完成批量更新 for test2_id, test1_id in update_pairs.items(): test2.loc[test2["ID"] == test2_id, ["Label", "Key"]] = id_map.loc[test1_id].values
方法3:用replace批量处理(适用于大规模替换场景)
如果test2中需要更新的ID可以直接对应到test1的ID映射,也可以用replace方法批量完成:
# 从test1构造Label和Key的基础映射字典 label_map = test1.set_index("ID")["Label"].to_dict() key_map = test1.set_index("ID")["Key"].to_dict() # 扩展映射,把test2需要更新的ID指向对应test1的ID的值 label_map.update({ "Ke2821Kkkkkk": label_map["Ka1129Kkkkkk"], "Ka83acKkkkkk": label_map["Ka9045Kkkkkk"], "Ka9a40Kkkkkk": label_map["Ka1129Kkkkkk"] }) key_map.update({ "Ke2821Kkkkkk": key_map["Ka1129Kkkkkk"], "Ka83acKkkkkk": key_map["Ka9045Kkkkkk"], "Ka9a40Kkkkkk": key_map["Ka1129Kkkkkk"] }) # 批量替换NaN值 test2["Label"] = test2["Label"].fillna(test2["ID"].map(label_map)) test2["Key"] = test2["Key"].fillna(test2["ID"].map(key_map))
以上三种方法都能解决索引不匹配的问题,其中方法2和3更适合批量更新的场景,代码可读性和可维护性更强。
内容的提问来源于stack exchange,提问作者Ailurophile
相关产品推荐
相关产品推荐

