我最近读到了collapse包,并尝试将下面的data.table
代码翻译为collapse
,看看它在真实的世界的例子中是否更快。
下面是我的data.table
代码:
library(data.table)
library(nycflights13)
data("flights")
flights_DT <- as.data.table(flights)
val_var <- "arr_delay"
id_var <- "carrier"
by <- c("month", "day")
flights_DT[
j = list(agg_val_var = sum(abs(get(val_var)), na.rm = TRUE)),
keyby = c(id_var, by)
][
i = order(-agg_val_var),
j = list(value_share = cumsum(agg_val_var)/sum(agg_val_var)),
keyby = by
][
j = .SD[2L],
keyby = by
][
order(-value_share)
]
#> month day value_share
#> 1: 10 3 0.5263012
#> 2: 1 24 0.5045664
#> 3: 1 20 0.4885145
#> 4: 10 17 0.4870692
#> 5: 3 6 0.4867606
#> ---
#> 361: 5 4 0.3220295
#> 362: 6 15 0.3205974
#> 363: 1 28 0.3197260
#> 364: 11 25 0.3161550
#> 365: 6 14 0.3128286
创建于2021-03-11由reprex package(v1.0.0)
我成功地翻译了第一个data.table
调用,但后来遇到了困难。
如果能看到如何使用collapse
来处理这个用例,那就太好了。
1条答案
按热度按时间p1iqtdky1#
因此,在这方面,我想指出的第一件事是,
collapse
不是,也可能永远不会是一个像dplyr
或data.table
那样的成熟的拆分-应用合并计算工具。它的重点不是按组最佳地执行任意代码表达式,而是通过其提供的广泛的基于C++的统计和数据转换功能提供高级和高效的分组,加权,时间序列和面板数据计算。我参考collapse
和data.table
上的vignette,以进一步清楚这些要点以及集成示例。因此,我认为只有在以下情况下才有意义将
data.table
代码转换为collapse
:(1)你在data.table
中想出了一个《双城之战》的表达式来完成它不擅长的复杂统计学(例如加权聚合、按组计算分位数或众数、对不规则面板进行滞后/差分,分组中心或线性/多项式拟合)(2)你实际上不需要data.table
对象,但更愿意使用vectors / matrices / data.frame's/tibles(3)你想写一个统计程序,并且更喜欢标准求值编程而不是NS eval和data.table
语法或(4)collapse
确实对你的特定应用程序来说更快。现在来看看你提供的具体代码。它混合了标准和非标准评估(例如通过使用
get()
),这是collapse
不太擅长的。我会给予你3个解决方案,从完整的NS eval到完整的标准eval base R风格编程。创建于2021-03-12由reprex package(v0.3.0)
请注意,使用
na.last = NA
实际上消除了缺少agg_val_var
的情况。这里需要这样做,因为fsum(NA)
是NA
,而不是像sum(NA, na.rm = TRUE)
那样的0
。现在,混合示例可能接近您提供的代码:创建于2021-03-12由reprex package(v0.3.0)
这里请注意,我在最后使用了
frename
来给予结果列命名,因为在collapse
的同一个函数中不能混合使用标准和非标准eval。最后,collapse
的一个很大的优点是,你可以用它来进行非常低级的编程:创建于2021-03-12由reprex package(v0.3.0)
我建议您参考关于programming with
collapse
的博客文章,以获得更有趣的例子,说明这如何有利于统计代码的开发。现在为了评估,我将这些解决方案 Package 在函数中,其中
DT()
是您提供的data.table
代码,在windows机器上使用2个线程运行。这将检查相等性:现在是基准测试:
如果你关心这几毫秒,请随意优化,但对于340,000个obs,所有解决方案都非常快。