在Pandas DataFrame子集(副本)上设置值很慢

Ale*_*lex 15 python performance dataframe pandas

import timeit
import pandas as pd
import numpy as np

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

dft = df[[True, False] * 5]
# df = dft
dft2 = dft.copy()

new_data = np.random.rand(5, 10)

print(timeit.timeit('dft.loc[:, :] = new_data', setup='from __main__ import dft, new_data', number=100))
print(timeit.timeit('dft2.loc[:, :] = new_data', setup='from __main__ import dft2, new_data', number=100))
Run Code Online (Sandbox Code Playgroud)

在我的笔记本电脑上,dft(原始子集)中的设置值比dft2(深层副本dft)中的设置值慢约160倍.

为什么会这样?

编辑:删除了有关代理对象的推测.

如c.皮革建议,这可能是因为在copy(dft)与原始dataframe()上设置值时,代码路径不同dft2.

奖金问题:删除对原始DataFrame的引用df(通过取消注释该df = dft行),在我的笔记本电脑上将速度因子降低到大约2.知道为什么会这样吗?

rll*_*rll 5

这并不是关于SO的新问题。,和是相关的职位。这是对当前文档进行说明的链接

@ c.leather的评论正确无误。问题在于,这dft是一个视图,而不是数据帧的副本df,如链接文章中所述。但是熊猫无法知道它是否真的是副本,以及该操作是否安全,因此要进行大量检查以确保执行分配是安全的,只需简单地避免复制。

这是一个相关的问题,在Github上有整个讨论。我看到了很多建议,我最喜欢的建议是文档应该鼓励这种df[[True,False] * 5].copy()成语,有人可以称其为切片和复制成语。

我找不到确切的检查,在github问题上,仅通过一些推文提到了此性能细微差别,一些开发人员发布了该行为。也许更多参与熊猫开发的人可以增加一些投入。