为什么pandas的reindex()函数不是原地操作的?

17

reindex 文档 中得知:

使用可选的填充逻辑将 DataFrame 转换为新的索引,将 NA/NaN 放置在先前索引中没有值的位置。除非新索引等同于当前索引且 copy=False,否则会生成一个新对象。

因此,我认为通过在原地设置 copy=False 我将获得重新排序的 Dataframe。 然而,现实是我确实得到了副本,并需要将其重新赋值给原始对象。 如果可以避免(原因来自此其他问题),我不想将其重新赋值回来。

这是我正在做的:

import numpy as np
import pandas as pd

df = pd.DataFrame(np.random.rand(5, 5))

df.columns = [ 'a', 'b', 'c', 'd', 'e' ]

df.head()

优势:

          a         b         c         d         e
0  0.234296  0.011235  0.664617  0.983243  0.177639
1  0.378308  0.659315  0.949093  0.872945  0.383024
2  0.976728  0.419274  0.993282  0.668539  0.970228
3  0.322936  0.555642  0.862659  0.134570  0.675897
4  0.167638  0.578831  0.141339  0.232592  0.976057

重建索引可以给我正确的输出,但我需要将其重新赋值给原始对象,这正是我想通过使用copy=False避免的:

df.reindex( columns=['e', 'd', 'c', 'b', 'a'], copy=False )

在那一行之后,期望的输出是:

          e         d         c         b         a
0  0.177639  0.983243  0.664617  0.011235  0.234296
1  0.383024  0.872945  0.949093  0.659315  0.378308
2  0.970228  0.668539  0.993282  0.419274  0.976728
3  0.675897  0.134570  0.862659  0.555642  0.322936
4  0.976057  0.232592  0.141339  0.578831  0.167638

copy=False在原地不起作用的原因是什么?

这个是否有可能实现?


使用Python 3.5.3和Pandas 0.23.3


3
您需要将 df 重新索引,并按顺序指定列名称,将其赋值给 df,代码如下:df = df.reindex(columns=['e', 'd', 'c', 'b', 'a']) - BENY
2个回答

20

reindex 是一种结构性变化,而不是美容或变形的变化。因此,由于该操作不能在原地执行(它需要为底层数组分配新的内存等),所以总是返回一个副本。这意味着您必须将结果重新赋值回去,没有其他选择。

df = df.reindex(['e', 'd', 'c', 'b', 'a'], axis=1)  

另请参阅GH21598上的讨论。


copy=False实际上有用的唯一一个特例是当用于重新索引df的索引与其已有的索引相同时。 您可以通过比较id来检查:

id(df)
# 4839372504

id(df.reindex(df.index, copy=False)) # same object returned 
# 4839372504

id(df.reindex(df.index, copy=True))  # new object created - ids are different
# 4839371608  

2
确实很有趣。但如果我可以说的话,它也很误导人。无论如何,谢谢,如果你碰巧学到了新东西,我很乐意听听 :) - Luis
顺便说一下,我想把问题保持开放一段时间,也许还有人有什么要补充的... - Luis
如果你事先不知道你要重新索引的内容,并且想要在代码中获得最佳性能,那么我认为你会将copy=False。显然,如果你不需要生成大量数据的副本,那么不生成副本将会更快,根据我的测试结果可以快5倍左右。 @Luis - cs95
这个用例是有意义的,当然:if cond: new_index = something; else: new_index = current_index → 对于那些 else 情况,copy=False;不过我会把 reindex 放在 if 里面:P - Luis
@Luis 当然,如果它是一个独立的操作,那么无论哪种方式都没关系,但是当你尝试链接很多方法时,实际上它非常有用,这在pandas中经常发生。以下是一个例子,通过方法链接的强大功能,解决了复杂的重塑操作:https://dev59.com/eFUL5IYBdhLWcg3wK1cU#50731254 - cs95
显示剩余2条评论

-1
有点离题,但我相信这将直接重新排列列。
    for i, colname in enumerate(list_of_columns_in_desired_order):
        col = dataset.pop(colname)
        dataset.insert(i, colname, col)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接