如何为多索引DataFrame的切片赋值(从另一切片计算取值)
问题描述
我有一个pandas多索引DataFrame,需要基于同一层级索引(tstep),将某一切片的值设置为另一切片经计算后的值。尝试用loc赋值,但目标切片全部变成NaN。以下是示例代码和问题详情:
示例DataFrame代码
iterables = [ [1, 2, 3, 4], ["A", "B"]] idx = pd.MultiIndex.from_product(iterables, names=["tstep", "trial"]) df = pd.DataFrame(index=idx) df['Value'] = 0.0 df.loc[(1,'A'), 'Value'] = 1.0 df.loc[(1,'B'), 'Value'] = 2.0
初始DataFrame
Value tstep trial 1 A 1.0 B 2.0 2 A 0.0 B 0.0 3 A 0.0 B 0.0 4 A 0.0 B 0.0
需求与错误代码
需求:将tstep=2的所有元素设置为tstep=1的元素值加1。
我写的代码:
df.loc[2]['Value'] = df.loc[1]['Value'] + 1.0
期望输出
Value tstep trial 1 A 1.0 B 2.0 2 A 2.0 B 3.0 3 A 0.0 B 0.0 4 A 0.0 B 0.0
实际输出
Value tstep trial 1 A 1.0 B 2.0 2 A NaN B NaN 3 A 0.0 B 0.0 4 A 0.0 B 0.0
注意:赋值单个标量时能正常工作,调换['Value']与.loc[2]顺序结果相同。请问哪里操作错了?
问题原因与解决方法
错误原因
你使用了链式索引df.loc[2]['Value'],这种写法会返回原DataFrame的副本而非视图。对副本赋值不会修改原DataFrame,反而会因为pandas的内部机制导致原DataFrame对应位置被设为NaN。
pandas中,链式索引(如df[a][b])很容易触发返回副本的场景,此时赋值操作仅修改了临时生成的副本,原数据不会得到更新,甚至会产生意外的NaN。
正确解法
要直接对原DataFrame的视图进行赋值,需采用单层loc索引访问,把列名整合到loc的第二个参数中:
df.loc[2, 'Value'] = df.loc[1, 'Value'] + 1.0
这样就能正确修改原DataFrame,得到预期的输出结果。
另外,也可以用更明确的多索引写法实现相同效果:
df.loc[(2, slice(None)), 'Value'] = df.loc[(1, slice(None)), 'Value'] + 1.0
这里slice(None)表示匹配tstep=2下的所有trial层级元素。
内容的提问来源于stack exchange,提问作者user3311717
相关产品推荐
相关产品推荐

