为何Pandas MultiIndex数据框.loc赋值无法实现(i,j)与(j,i)行相等?
原代码无效的原因
你的代码核心问题在于过滤后的idx1和idx2元素顺序不匹配,导致按顺序赋值时出现错位:
- 过滤后,
idx1是原索引中存在对应反向索引的项,比如[(1,1), (1,2), (2,1), (2,2)]; idx2是对应的反向索引列表,比如[(1,1), (2,1), (1,2), (2,2)];- 执行
df.loc[idx2] = df.loc[idx1].values时,是把idx1列表第n个元素的值直接赋值给idx2列表第n个元素的位置,而非将每个(j,i)赋值为对应(i,j)的值。例如idx2中的(2,1)被赋了idx1中(1,2)的值,idx2中的(1,2)被赋了idx1中(2,1)的值; - 最终比较时,
df.loc[idx1]和df.loc[idx2]的values数组顺序错位,因此返回False。
正确实现方式
要让每个(i,j)和(j,i)的行相等,需确保每个反向索引(j,i)都被赋值为对应原索引(i,j)的值,以下是两种可行方案:
方案1:精准映射反向索引赋值
直接遍历反向索引,找到对应的原索引后赋值:
np.random.seed(0) idx1 = pd.MultiIndex.from_product([list(range(3)), list(range(1,4))]) df = pd.DataFrame(np.random.randint(0,100,9*2).reshape(9,2), index=idx1) # 筛选出存在对应反向索引的项 valid_pairs = [pair for pair in idx1 if (pair[1], pair[0]) in idx1] # 生成对应的反向索引列表 reverse_pairs = [(pair[1], pair[0]) for pair in valid_pairs] # 为每个反向索引赋值对应原索引的值 df.loc[reverse_pairs] = df.loc[valid_pairs].values # 验证所有对称行相等 print(all(df.loc[pair].equals(df.loc[(pair[1], pair[0])]) for pair in valid_pairs))
方案2:用reindex自动匹配索引
利用reindex按索引匹配取值,避免顺序错位:
np.random.seed(0) idx1 = pd.MultiIndex.from_product([list(range(3)), list(range(1,4))]) df = pd.DataFrame(np.random.randint(0,100,9*2).reshape(9,2), index=idx1) # 生成所有反向索引 reverse_idx = pd.MultiIndex.from_tuples([(j,i) for (i,j) in idx1]) # 过滤出原索引中存在的反向索引 valid_reverse_idx = reverse_idx[reverse_idx.isin(idx1)] # 按索引匹配取值后赋值 df.loc[valid_reverse_idx] = df.reindex([(j,i) for (i,j) in valid_reverse_idx]).values # 验证结果 print(np.all(df.loc[[(j,i) for (i,j) in valid_reverse_idx]].values == df.loc[valid_reverse_idx].values))
额外优化:合并对称行的值(可选)
如果希望对称行取两者的均值(或其他合并方式)而非直接覆盖,可以这样做:
for pair in valid_pairs: reverse_pair = (pair[1], pair[0]) if pair != reverse_pair: # 跳过(i,i)这类自对称索引 mean_val = (df.loc[pair] + df.loc[reverse_pair]) / 2 df.loc[pair] = mean_val df.loc[reverse_pair] = mean_val
内容的提问来源于stack exchange,提问作者nicholas sterling
相关产品推荐
相关产品推荐

