为何链式调用中drop_duplicates(inplace=True)无法修改原DataFrame?
问题:链式调用原地去重为何不生效?
示例数据
data = [[1, 'john@example.com'], [2, 'bob@example.com'], [3, 'john@example.com']] person = pd.DataFrame(data, columns=['id', 'email']).astype({'id':'int64', 'email':'object'})
可复现代码(不生效的链式调用)
(person.sort_values(by = ['email', 'id'], ascending = [True, True]) .drop_duplicates(subset = 'email', keep = 'first', inplace = True))
预期结果
id email 1 2 bob@example.com 0 1 john@example.com
实际结果(原person未变化)
id email 0 1 john@example.com 1 2 bob@example.com 2 3 john@example.com
生效的拆分写法
person1 = person.sort_values(by = ['email', 'id'], ascending = [True, True]) person1.drop_duplicates(subset = 'email', keep = 'first', inplace = True)
此时person1符合预期:
id email 1 2 bob@example.com 0 1 john@example.com
原因解释
核心问题出在**sort_values()默认返回原DataFrame的副本**,而非直接操作原对象。
链式调用时,person.sort_values(...)会生成一个全新的临时DataFrame对象,后续的drop_duplicates(inplace=True)确实原地修改了这个临时对象,但这个临时对象没有被赋值给任何变量,操作完成后就被Python垃圾回收了,完全碰不到原来的person变量,所以原person自然保持原样。
而拆分写法中,我们把sort_values()返回的副本赋值给了person1,此时drop_duplicates(inplace=True)修改的是person1指向的这个副本,所以能看到预期效果。
正确的链式调用写法(修改原对象)
如果想用链式调用同时修改原person,不要用inplace=True,而是把链式调用的结果重新赋值给person:
person = person.sort_values(by=['email', 'id'], ascending=[True, True])\ .drop_duplicates(subset='email', keep='first')
这样person就会被替换成排序并去重后的新DataFrame,达到预期效果。
内容的提问来源于stack exchange,提问作者Amazonian
相关产品推荐
相关产品推荐

