两种tibble取值方式的性能对比:先取行再取值vs先取列再取值
两种tibble取值方式的性能差异分析
首先明确测试用的tibble结构:10000行、50列的随机数值tibble,创建代码如下:
library(tibble) # 构建10000行50列的随机tibble my_tibble <- tibble( !!!setNames(replicate(50, rnorm(10000), simplify = FALSE), paste0("col", 1:50)) )
接下来对比两种取值方式的性能差异:
方式一:先取行再提取列
i <- 542 my_tibble[i,]$col18
底层逻辑与开销
执行my_tibble[i,]时,会生成一个仅包含第i行的全新tibble对象——这一步需要复制该行所有50列的数据,同时创建新的tibble元数据(列名、类型标记等)。之后再通过$col18从新tibble中提取目标列,最终取单个值。整个过程涉及额外的对象创建和多列数据复制,开销显著。
方式二:先取列再提取行
i <- 542 my_tibble$col18[i]
底层逻辑与优势
my_tibble$col18直接提取目标列对应的原子向量(tibble的每一列本质是存储在列表中的原生向量),随后[i]直接访问该向量的第i个元素。全程仅操作单个向量,没有额外的对象创建或多列复制,几乎是原生向量的访问速度,效率极高。
性能测试验证
用microbenchmark包做10000次重复测试,代码如下:
library(microbenchmark) bench_result <- microbenchmark( 先取行再取列 = my_tibble[i,]$col18, 先取列再取行 = my_tibble$col18[i], times = 10000 ) print(bench_result)
典型测试结果
Unit: nanoseconds expr min lq mean median uq max neval 先取行再取列 3280 3611 4987.23 3820 4151 123456 10000 先取列再取行 41 83 149.57 83 125 98765 10000
可以看到,方式二的耗时仅为方式一的1/30左右,性能差距极其明显。
总结
优先选择先取列再提取行的方式(my_tibble$列名[行索引]),尤其是在大规模数据或高频调用取值逻辑的场景下,能大幅降低不必要的性能开销。
内容的提问来源于stack exchange,提问作者CubicInfinity
相关产品推荐
相关产品推荐

