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
(原始子集)比设置值慢大约 160 倍dft2
(深拷贝dft
).
为什么会这样呢?
Edit:删除了有关代理对象的猜测。
作为c。 Leather 表明,这可能是因为在副本上设置值时使用了不同的代码路径(dft
) 与原始数据框 (dft2
).
额外问题:删除对原始 DataFrame 的引用df
(通过取消注释df = dft
线),在我的笔记本电脑上将速度系数降低到大约 2。知道为什么会这样吗?
这不完全是一个新问题。This https://stackoverflow.com/questions/22532302/pandas-peculiar-performance-drop-for-inplace-rename-after-dropna, and this https://stackoverflow.com/questions/17960511/pandas-subindexing-dataframes-copies-vs-views是相关帖子。这是当前文档的链接 http://pandas-docs.github.io/pandas-docs-travis/indexing.html?highlight=view#indexing-view-versus-copy这就解释了这一点。
@c.leather 的评论是正确的。问题是dft
是一个视图,而不是数据框的副本df
,如链接文章中所述。但是 pandas 无法知道它是否真的是副本以及操作是否安全,因此需要进行大量检查以确保执行分配是安全的,而这可以通过简单地避免复印。
这是一个相关问题,在Github https://github.com/pydata/pandas/issues/10954。我看到了很多建议,我最喜欢的一个是文档应该鼓励df[[True,False] * 5].copy()
习语,我们可以将其称为“切片和复制”习语。
我找不到确切的检查,并且在 github 问题上,仅通过一些开发人员发布的一些推文提到了这种性能细微差别,指出了这种行为。也许更多参与 pandas 开发的人可以添加更多的意见。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)