访问相同dtype DataFrame中的行和列

时间:2019-03-08 18:33:41

标签: python pandas 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    

对于dataFrame的存储方式,我肯定不太了解,谢谢您的帮助!

2 个答案:

答案 0 :(得分:0)

如果您查看基础的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)

答案 1 :(得分:0)

我不是Pandas实施细节方面的专家,但是我已经使用了足够多的知识,可以做出有根据的猜测。

据我了解,Pandas数据结构与字典字典最直接可比,字典的字典中第一个索引是列。因此,DF:

   a b
 c 1 2
 d 3 4

本质上是{'a': {'c': 1, 'd': 3}, 'b': {'c': 2, 'd': 4}}。我假设我从现在开始对这个主张是正确的,如果有人对熊猫了解更多,我希望得到纠正。

因此,索引一列是一个简单的哈希查找,而索引一行则需要遍历所有列并对每个列进行哈希查找。

我认为其原因是,这使得访问所有行的特定属性并添加新列确实非常有效,这通常是您与数据框进行交互的方式。对于这样的表格用例,它比简单的矩阵布局要快得多,因为您不必大步跨过内存(整列或多或少都存储在本地),但这当然是一个折衷,这使与行的交互效率降低了(因此,从语法上讲,这样做并不容易;您会注意到,大多数Pandas操作默认都与列进行交互,而与行进行交互或多或少是模块中的第二个目标。)