R基准测试中Base R排序快于dplyr、data.table的原因及适用性疑问
你的测试代码存在核心错误,导致结果完全不具备参考性
错误原因说明
- 所有测试用例的排序函数传参方式完全错误,没有执行你预期的按
Petal.Width.y列排序的逻辑:- Base R用例存在两个低级错误:
base::order("Petal.Width.y")传入的是字符串常量,不是数据集的列,order()对单个字符串排序只会返回索引1- 数据框取行语法缺失逗号,
iris_big[索引]是取列而非取行,你的操作本质只是取出数据集的第1列,完全没有执行排序操作,所以耗时接近0
- dplyr用例错误:
dplyr::arrange(iris_big,"Petal.Width.y")直接传入字符串不会被识别为列名,arrange()会将其识别为全局常量,相当于按同一个值对全表排序(等于没有重排),但dplyr的非标准评估机制会产生大量额外解析开销,所以耗时最高 - data.table用例错误:
data.table::setorder(iris_big_dt,"Petal.Width.y")同样是传入字符串常量未被识别为列名,本质也没有执行按指定列排序的操作,仅产生了少量函数调用开销,所以耗时略高于完全无操作的Base R用例
- Base R用例存在两个低级错误:
正确测试代码示例
library(dplyr) library(data.table) library(rbenchmark) # 生成测试数据集 iris_big <- merge(x = iris, y = iris, by = NULL) iris_big_dt <- as.data.table(iris_big) benchmark( "Base R" = { # 正确传入列,加逗号取行 iris_big[base::order(iris_big$Petal.Width.y), ] }, "dplyr" = { # 两种正确写法:直接写列名,或用.all_of接收字符串变量 dplyr::arrange(iris_big, Petal.Width.y) }, "data.table" = { # 正确传入列名,或用col参数接收字符串 data.table::setorder(iris_big_dt, Petal.Width.y) }, replications = 30, columns = c("test", "replications", "elapsed", "relative", "user.self", "sys.self") )
正确测试的常规结论
相同逻辑下的排序性能通常为:data.table > Base R > dplyr,小数据集下dplyr的性能差距主要来自非标准评估的固定开销,大数据集下三者的性能差距会明显缩小。
工具选择建议
性能只是选择数据处理工具的维度之一,还要综合考虑开发效率、代码可读性、功能完整性:
- 仅做简单基础操作、对性能要求极高的场景可以选择Base R
- 复杂数据清洗、转换、分组统计的场景,dplyr语法更简洁易读,开发效率远高于Base R
- 处理百万行以上超大规模数据集的场景,data.table的性能优势最明显,同时语法也比Base R更简洁,是最优选择
内容的提问来源于stack exchange,提问作者aStarIsCorn
相关产品推荐
相关产品推荐

