为啥 pandas reindex() 不就地运行?

Posted

技术标签:

【中文标题】为啥 pandas reindex() 不就地运行?【英文标题】:Why doesn't pandas reindex() operate in-place?为什么 pandas reindex() 不就地运行? 【发布时间】:2019-10-21 01:24:17 【问题描述】:

来自reindex docs:

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

因此,我认为通过将copy=False 设置到位(!),我会得到一个重新排序的Dataframe。但是,似乎我确实得到了一份副本,并且需要再次将其分配给原始对象。如果可以避免的话,我不想将其分配回去 (the reason comes from this other question)。

这就是我正在做的:

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

Reindex 为我提供了正确的输出,但我需要将其分配回原始对象,这是我想通过使用 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

【问题讨论】:

github.com/pandas-dev/pandas/issues/21598,您需要将其分配回df=df.reindex( columns=['e', 'd', 'c', 'b', 'a']) 【参考方案1】:

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  

【讨论】:

难以理解这一点...想想...这是否意味着copy= 被实现为与True 一起使用,但不是与False 一起使用?你的意思是……重新索引并分配给一个新的数据框,同时保持预索引? @Luis 如果对 reindex 的调用实际上并没有导致 DataFrame 被重新索引,那么您是否希望 pandas 浪费时间生成您已经拥有的数据的副本? (我不知道,但这个论点是存在的,所以我认为它对某个地方的某个人有用。) 确实很有趣。并且误导,如果我可以说的话。无论如何,谢谢,如果你碰巧学到了新东西,我很乐意听到:) 顺便说一句,我想暂时搁置这个问题,也许其他人有什么要补充的...... @Luis 如果您事先不知道要使用什么重新索引并希望从代码中获得最高性能(显然,不生成如果您不需要,复制大量数据会更快 - 根据我的测试大约快 5 倍)。【参考方案2】:

有点跑题了,但我相信这会重新排列适当的列

    for i, colname in enumerate(list_of_columns_in_desired_order):
        col = dataset.pop(colname)
        dataset.insert(i, colname, col)

【讨论】:

以上是关于为啥 pandas reindex() 不就地运行?的主要内容,如果未能解决你的问题,请参考以下文章

pandas入门

Pandas - DataFrame reindex 函数返回警告

使用带有浮点数的 pandas reindex:插值

pandas 中 df.reindex() 和 df.set_index() 方法的区别

pandas功能使用rename, reindex, set_index 详解

pandas --index ,reindex, set_index, reset_index , reindex_like函数 之 set_index