python - 访问同一 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
关于数据帧的存储方式,我肯定有一些不太了解的地方,感谢您的帮助!
解决方案
如果您查看底层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)
推荐阅读
- javascript - Firebase 模拟器上的 Firebase 权限被拒绝错误
- flutter - Flutter,检测到其他应用程序已启动
- javascript - 如何获取具有值的对象键
- javascript - 如何以比下面使用的索引方法更好的方式检查特定对象并且该特定对象是唯一对象?
- flutter - Flutter 命令提示符在 Windows 下不起作用
- performance - 在 K6 执行性能测试期间观察到更多“dial tcp : I/O timeout”
- kubernetes - kubernetes 上的 redis-cluster:连接超时
- python - 如何修改 Django ModelForm 的 Unique 和 ForeignKey
- django - 使用 Apache mod_wsgi 在 CentOS7 上配置 Django WebApp
- laravel - 由于尝试将总和放入数组而导致的未定义偏移错误