首页 > 解决方案 > 访问同一 dtype DataFrame 中的行和列

问题描述

对于一个独特的 dtype DataFrame (nxn dataFrame),访问一行比访问一列慢,我有点惊讶。根据我收集的数据,相同 dtype 的 DataFrame 应该作为一个连续的块存储在内存中,因此访问行或列应该同样快(只是更新正确步幅的问题)。

示例代码:

df = pd.DataFrame(np.random.randn(100, 100))

%timeit df[0]
%timeit df.loc[0]

最慢的运行时间是最快的运行时间的 12.86 倍。这可能意味着正在缓存中间结果。

100000 loops, best of 3: 2.72 µs per loop
10000 loops, best of 3: 116 µs per loop    

关于数据帧的存储方式,我肯定有一些不太了解的地方,感谢您的帮助!

标签: pythonpandasdataframe

解决方案


如果您查看底层numpy数组,您会发现行/列的访问速度相同,至少在我的测试中:

%timeit df.values[0]
# 10.2 µs ± 596 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit df.values[:, 0]
# 10.2 µs ± 730 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

在数据框中,系列(列)比行更多是一等公民。我认为访问这些列更像是一个字典查找,这就是它如此之快的原因。通常有很少的列,而且每一列都是有意义的,所以以这种方式存储它们是有意义的。但是,通常有很多行,而单独的行没有那么重要。不过,这有点猜想。您必须查看源代码以查看每次实际调用的内容,并从中确定为什么操作需要不同的时间 - 也许稍后会弹出答案。

这是另一个时间比较:

%timeit df.iloc[0, :]
# 141 µs ± 7 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit df.iloc[:, 0]
# 61.9 µs ± 1.76 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

以这种方式访问​​列也更快,但速度要慢得多。我不确定如何解释这一点。我假设与直接访问行/列相比的减速来自需要返回一个pd.Series. 访问一行时,pd.Series可能需要创建一个新行。但我不知道为什么iloc列的速度也较慢 - 也许它每次也会创建一个新系列,因为iloc可以非常灵活地使用并且可能不会返回现有系列(或可能返回数据框)。但是,如果两次都创建了一个新系列,那么我再次对为什么一个操作胜过另一个操作感到困惑。

为了更完整

%timeit df.loc[0, :]
# 155 µs ± 6.48 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit df.loc[:, 0]
# 35.6 µs ± 1.28 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

推荐阅读