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

时间:2016-07-01 23:29:03

标签: python performance pandas dataframe

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))

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

为什么会这样?

修改:删除了有关代理对象的推测。

作为c。皮革建议,这可能是因为在副本(dft)上设置值与原始数据帧(dft2)时的代码路径不同。

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

1 个答案:

答案 0 :(得分:5)

这不是一个关于SO的新问题。 Thisthis是相关帖子。 This is the link to the current docs解释了它。

@ c.leather的评论是正确的。问题是dft是一个视图,而不是数据框df的副本,如链接文章中所述。但是大熊猫不知道它是否真的是一个副本,如果操作是否安全,并且因此有很多检查确保执行任务是安全的,并且可以通过简单的方法避免制作副本。

这是一个相关问题,在Github进行了全面讨论。我看过很多建议,我最喜欢的是文档应该鼓励df[[True,False] * 5].copy()成语,可以称之为切片&复制成语。

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