【发布时间】:2016-11-04 10:21:33
【问题描述】:
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(原始子集)中的设置值比dft2(dft 的深层副本)中的设置值慢大约 160 倍。
为什么会这样?
编辑:移除关于代理对象的推测。
作为c。皮革建议,这可能是因为在副本 (dft) 与原始数据帧 (dft2) 上设置值时的代码路径不同。
额外问题:删除对原始 DataFrame df 的引用(通过取消注释 df = dft 行),在我的笔记本电脑上将速度因子降低到大约 2。知道为什么会这样吗?
【问题讨论】:
-
在底层,
df[[True, False] * 5]调用Dataframe.__getitem__()当索引器是一个列表时调用Dataframe._getitem_array()。这反过来又调用Dataframe.take(),它有一个属性is_copy。我发现如果我运行df.take([0,2,4,6,8], is_copy=True),我的速度会比df.take([0,2,4,6,8], is_copy=False)慢,在您的示例中 is_copy=True 产生与 dft 相同的运行时间,而 is_copy=False 产生与 dft2 相同的运行时间。因此,由于这个 is_copy 属性,可能在Dataframe.__setitem__期间出现减速。 -
然而,is_copy 属性的实际用途非常模糊,可能需要深入了解
__setitem__。我认为您对返回的数组作为视图/代理的感觉很好,我认为这与此属性有关。 -
谢谢@c.leather。想知道这些检查是什么。
标签: python performance pandas dataframe