使用“{data.table}”编程:如何命名新列?

Emm*_*man 5 r data.table

下面的问题在编程中似乎非常基本data.table,所以如果它是重复的,我很抱歉。我花了时间研究但找不到答案。

我想创建一个“用户定义的函数”来包装data.table争论过程。在此过程中,创建了一个新列,我想让用户设置该新列的名称。

例子

考虑以下按原样工作的代码。我想将它包装在一个函数中。

library(data.table)
library(magrittr)
library(tibble)

mtcars %>%
  as.data.table() %>%
  .[, .(max_mpg = max(mpg)), by = cyl] %>%
  as_tibble()
#> # A tibble: 3 x 2
#>     cyl max_mpg
#>   <dbl>   <dbl>
#> 1     6    21.4
#> 2     4    33.9
#> 3     8    19.2
Run Code Online (Sandbox Code Playgroud)

由reprex 包于 2021 年 10 月 13 日创建(v0.3.0)

我希望我的函数做的就是让用户设置以下名称new_colname_of_choice:

my_wrapper <- function(new_colname_of_choice) {
  mtcars %>%
    as.data.table() %>%
    .[, .(new_colname_of_choice = max(mpg)), by = cyl] %>%
    as_tibble()
}


my_wrapper(new_colname_of_choice = "my_lovely_colname")
#> # A tibble: 3 x 2
#>     cyl new_colname_of_choice <---------- why this isn't called "my_lovely_colname"?
#>   <dbl>                 <dbl>
#> 1     6                  21.4
#> 2     4                  33.9
#> 3     8                  19.2
Run Code Online (Sandbox Code Playgroud)

我尝试过使用大括号,但也不起作用(实际上引发了错误):

my_wrapper_2 <- function(new_colname_of_choice) {
  
  mtcars %>%
    as.data.table() %>%
    .[, .({new_colname_of_choice} = max(mpg)), by = cyl] %>%
    as_tibble()
  
}
Run Code Online (Sandbox Code Playgroud)

错误:意外的“=”:“ as.data.table() %>% .[, .({new_colname_of_choice} ="

这是令人惊讶的,因为花括号确实促进了所需的命名能力,但在不同(但相似)类型的代码中:

my_wrapper_3 <- function(new_colname_of_choice) {
  mtcars %>%
    as.data.table() %>%
    .[, {new_colname_of_choice} := max(mpg), by = cyl] %>%
    as_tibble()
}


my_wrapper_3(new_colname_of_choice = "my_lovely_colname")

## # A tibble: 32 x 12
##      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb my_lovely_colname <---- SUCCESS!
##    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>             <dbl>
##  1  21       6  160    110  3.9   2.62  16.5     0     1     4     4              21.4
##  2  21       6  160    110  3.9   2.88  17.0     0     1     4     4              21.4
##  3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1              33.9
##  4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1              21.4
##  5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2              19.2
##  6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1              21.4
##  7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4              19.2
##  8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2              33.9
##  9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2              33.9
## 10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4              21.4
## # ... with 22 more rows
Run Code Online (Sandbox Code Playgroud)

底线

我的结论是操作员对LHS=很敏感。{...}在最初的示例中,我如何才能将名称(来自参数)传递给 LHS my_wrapper()?


编辑


我想添加dplyr同一问题的解决方案,取自dplyr vignette的编程:

library(dplyr)

my_wrapper_dplyr <- function(new_colname_of_choice) {
  mtcars %>%
    group_by(cyl) %>%
    summarise("{new_colname_of_choice}" := max(mpg))
}

my_wrapper_dplyr("another_lovely_colname")
Run Code Online (Sandbox Code Playgroud)

它非常强大,适用于我遇到的所有命名情况。data.table是否有类似于 的内置/规范实践{dplyr}?

Wal*_*ldi 7

在即将发布的data.table 版本 1.14.3中,您将能够使用新env参数:

添加了用于在 data.table 上进行编程的新接口,解决了 #2655 和许多其他相关问题。它是使用基本 R 的类似替代接口通过 [.data.table. 有关详细信息,请参阅data.table 上的新 vignette编程以及新的 ?substitute2 手册页。感谢众多用户提出请求,并感谢 Jan Gorecki 的实施。

# install dev version
install.packages("https://github.com/Rdatatable/data.table/archive/master.tar.gz",  repo = NULL, type = "source")

library(tibble)
library(data.table)

my_wrapper_new <- function(new_colname_of_choice) {
  
  mtcars %>%
    as.data.table() %>%
    .[, .(new_colname_of_choice = max(mpg)), by = cyl, 
      env=list(new_colname_of_choice = new_colname_of_choice)] %>%
    as_tibble()
  
}

my_wrapper_new('test')

# A tibble: 3 x 2
    cyl  test
  <dbl> <dbl>
1     6  21.4
2     4  33.9
3     8  19.2

Run Code Online (Sandbox Code Playgroud)