r - 从 data.table 中获取排序的唯一值向量的最快方法是什么?

标签 r dataframe data.table

这个 answerquestion (Unique sorted rows single column from R data.table) 建议了三种不同的方法来从 data.table 获取排序的唯一值的向量:

# 1
sort(salesdt[, unique(company)])
#2 
sort(unique(salesdt$company))
#3
salesdt[order(company), unique(company)]

另一个 answer 建议了除字典顺序之外的其他排序选项:
salesdt[, .N, by = company][order(-N), company]
salesdt[, sum(sales), by = company][order(-V1), company]
data.table 是由
library(data.table)
company <- c("A", "S", "W", "L", "T", "T", "W", "A", "T", "W")
item <- c("Thingy", "Thingy", "Widget", "Thingy", "Grommit", 
          "Thingy", "Grommit", "Thingy", "Widget", "Thingy")
sales <- c(120, 140, 160, 180, 200, 120, 140, 160, 180, 200)
salesdt <- data.table(company,item,sales) 

与往常一样,如果有不同的选项可供选择,我开始想知道最好的解决方案是什么,特别是如果 data.table 会大得多。我在 SO 上进行了一些搜索,但到目前为止还没有找到特定的答案。

最佳答案

对于基准测试,使用 1.000.000 行创建更大的 data.table:

n <- 1e6
set.seed(1234) # to reproduce the data
salesdt <- data.table(company = sample(company, n, TRUE), 
                      item = sample(item, n, TRUE), 
                      sales = sample(sales, n, TRUE))

为了完整起见,还有变体
# 4
unique(sort(salesdt$company))
# 5
unique(salesdt[,sort(company)])

尽管很明显排序唯一值应该比其他方式更快,但将进行基准测试。

此外,还包括此 answer 中的另外两个排序选项:
# 6
salesdt[, .N, by = company][order(-N), company]
# 7
salesdt[, sum(sales), by = company][order(-V1), company]

编辑: 根据弗兰克的评论,我已经包含了他的建议:
# 8
salesdt[,logical(1), keyby = company]$company

基准测试,无 key 集

基准测试是在 microbenchmark 包的帮助下完成的:
timings <- microbenchmark::microbenchmark(
  sort(salesdt[, unique(company)]),
  sort(unique(salesdt$company)),
  salesdt[order(company), unique(company)],
  unique(sort(salesdt$company)),
  unique(salesdt[,sort(company)]),
  salesdt[, .N, by = company][order(-N), company],
  salesdt[, sum(sales), by = company][order(-V1), company],
  salesdt[,logical(1), keyby = company]$company
)

时间显示为
ggplot2::autoplot(timings)

请注意图表中的相反顺序(底部#1,顶部#8)。

enter image description here

正如预期的那样,变体 #4 和 #5(排序后唯一)非常慢。 编辑: #8 是最快的,这证实了弗兰克的评论。

对我来说有点惊讶的是变体 #3。尽管 data.table 的基数排序速度很快,但它的效率低于 #1 和 #2。似乎先排序,然后提取唯一值。

基准测试,由 company 键控的 data.table

受此观察的启发,我使用 data.table 键控的 company 重复了基准测试。
setkeyv(salesdt, "company")

时间显示(请不要改变时间轴的刻度)#4 和#5 已经通过键控显着加速。它们甚至比#3 还要快。请注意,下一部分包含变体 #8 的计时。

enter image description here

基准测试,稍作调整

变体 #3 仍然包含 order(company) 如果已经由 company 键入,则不需要。因此,我从#3 和#5 中删除了对 ordersort 的不必要调用:
timings <- microbenchmark::microbenchmark(
  sort(salesdt[, unique(company)]),
  sort(unique(salesdt$company)),
  salesdt[, unique(company)],
  unique(salesdt$company),
  unique(salesdt[, company]),
  salesdt[, .N, by = company][order(-N), company],
  salesdt[, sum(sales), by = company][order(-V1), company],
  salesdt[,logical(1), keyby = company]$company
)

时间现在在同一级别显示变体#1 到#4。 编辑: 同样,#8(弗兰克的解决方案)是最快的。

enter image description here

警告 :基准测试基于原始数据,其中仅包含 5 个不同的字母作为公司名称。对于大量不同的公司名称,结果可能会有所不同。结果已通过 data.table v.1.9.7 获得。

关于r - 从 data.table 中获取排序的唯一值向量的最快方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36953026/

相关文章:

r - 匹配包 : Combining "nearest neighbor" matching and "exact" matching

r - 安装路径不可写R,无法更新包

r - 迭代数据帧,其中每次迭代都有效地依赖于 R 中的前一项

r - 在多个绘图之间添加文本

python - 根据条件将 Pandas DataFrame 列从 String 转换为 Int

python - 在 df.apply() 中的自定义函数中传递 Pandas DataFrame 中的不同列

Python:去掉成对的列名称

r - 如何在data.table中引用以数字开头的列名

r - 在 R 中数据表的 by= 调用中循环编号变量

r - "object not found"当.SD 和.by 中的表达式一起使用时