pandas中=复制DataFrame后iloc切片为何未同步修改关联变量?
底层原理解释
这个现象核心是Python的变量赋值规则,加上Pandas不同操作的行为差异共同导致的,和你有没有用copy没有直接关系。
Python变量的基本逻辑
Python里的变量从来不是装数据的容器,只是贴在内存中实际对象上的名字条:
- 你写
df2 = df的时候,根本没有生成新的DataFrame,只是给内存里已经存在的那个3行的原始行星DataFrame,多贴了一张写着df2的名字条。这时候df和df2指的是完完全全同一个东西,你改这个对象里的内容,两个名字访问到的结果当然一起变。
这时候你跑id(df) == id(df2),结果肯定是True,两个变量指向同一块内存地址。
两次操作的本质区别
你前后两次写的带df的代码,行为逻辑完全不一样:
原地修改操作:df["mass"]["earth"] = 100
这行代码是直接钻进df和df2共同指向的那个原始DataFrame里,把对应位置的值改了,全程没有生成新的DataFrame对象。就好比你给同一个房子换了块窗玻璃,不管你从挂着df门牌号的入口进,还是从挂着df2门牌号的入口进,看到的都是换完的玻璃,两边同步变是正常的。
提一句:这种连续用方括号索引再赋值的写法属于链式索引,是Pandas官方不推荐的写法,有些场景下链式索引拿到的是数据副本而非原数据,会出现赋值了但结果没生效的问题,规范写法是用
.loc单步赋值:df.loc["earth", "mass"] = 100
变量重绑定操作:df = df.iloc[:2,:]
首先要明确:iloc做切片从来不会改原始的DataFrame,它的返回值是一个新生成的对象——根据切片规则不同,这个新对象可能和原对象共享部分底层数据(也就是常说的视图),也可能是完全独立的副本,但不管是哪种,它都是一个和原始3行DataFrame不同的新Python对象。
这行代码的执行顺序是两步:
- 先算等号右边:对着原始的3行DataFrame切前2行,生成一个只有2行数据的新DataFrame,存在内存的新位置
- 再做赋值:把原来贴在3行原始DataFrame上的、写着
df的名字条撕下来,贴到刚生成的2行新DataFrame上
整个过程里,写着df2的名字条从来没被碰过,它还牢牢贴在最开始那个3行的原始DataFrame上。这时候df和df2已经指到两个完全不同的对象上了,你再改df指向的新对象,和df2指的老对象一点关系都没有,自然不会同步更新。
这时候再跑id(df) == id(df2),结果肯定是False,直接能证明两个变量已经各指各的了。
内容的提问来源于stack exchange,提问作者Manh Linh Phan
相关产品推荐
相关产品推荐

