簡體   English   中英

將 data.table 列名傳遞給 function 使用:=

[英]Pass a data.table column name to a function using :=

這個問題是 data.table 相當於Pass a data.frame column name to a function

假設我有一個非常簡單的 data.table:

dat <- data.table(x = 1:4,
                  y = 5:8)

現在我想為任何給定的 function 創建一個新列:

new_column <- function(df,col_name,expr){
    col_name <- deparse(substitute(col_name))
    df[[col_name]] <- eval(substitute(expr),df,parent.frame())
    df
}

以便它正確地提供:

> new_column (dat,z,x+y)
  x y  z
1 1 5  6
2 2 6  8
3 3 7 10
4 4 8 12

但是,因為它是 data.table 我想使用:=創建這個新列:

new_column_byref <- function(df,col_name,expr){
   col_name <- deparse(substitute(col_name))
  df[, col_name:=eval(substitute(expr)
                      ,df
                      ,parent.frame()
                      )]
  df
}

但它不起作用:

> a <- new_column_byref(dat,z,x+y)
 Error: Check that is.data.table(DT) == TRUE. Otherwise, :=, `:=`(...) and let(...) are defined for use in j, once only and in particular ways. See help(":=").

我該如何解決? 謝謝你。

new_column_byref <- function(df,col_name,expr){
  col_name <- deparse(substitute(col_name))
  set(df,j=col_name,value=eval(substitute(expr),df,parent.frame()))
}


dat <- data.table(x = 1:4,y = 5:8)

new_column_byref(dat,z,x+y)[]

   x y  z
1: 1 5  6
2: 2 6  8
3: 3 7 10
4: 4 8 12

set是 data.table 慣用的方式。 如果您需要做其他事情,例如 use byrlang有一種通用的延遲評估的方法,即enexpr args(如果您希望在原始環境中評估它們,則為 enquo)和!! 將它們inject您通常使用的表達式中。

library(rlang)
#> Warning: package 'rlang' was built under R version 4.1.2
library(data.table)
#> 
#> Attaching package: 'data.table'
#> The following object is masked from 'package:rlang':
#> 
#>     :=

dat <- data.table(x = 1:4,
                  y = 5:8)

new_column <- function(df, col_name, expr) {
    col_name <- enexpr(col_name)
    expr <- enexpr(expr)
    inject(df[, !!col_name := !!expr])
}

new_column(dat, z, x + y)

dat
#>        x     y     z
#>    <int> <int> <int>
#> 1:     1     5     6
#> 2:     2     6     8
#> 3:     3     7    10
#> 4:     4     8    12

reprex package (v2.0.1) 創建於 2022-02-25

或者,同樣沒有 rlang

library(data.table)

dat <- data.table(x = 1:4,
                  y = 5:8)

new_column <- function(df, col_name, expr) {
    col_name <- deparse(substitute(col_name))
    expr <- substitute(expr)
    df[, (col_name) := eval(expr)]
}

new_column(dat, z, x + y)

dat
#>        x     y     z
#>    <int> <int> <int>
#> 1:     1     5     6
#> 2:     2     6     8
#> 3:     3     7    10
#> 4:     4     8    12

reprex package (v2.0.1) 創建於 2022-02-25

在開發版本中使用“語言編程”界面。

https://rdatatable.gitlab.io/data.table/news/index.html

library(data.table)
dat <- data.table(x = 1:4,
                  y = 5:8)

new_column <- function(df, col_name, expr) {
    df[, col_name := expr, 
       env = list(col_name = substitute(col_name), 
                  expr = substitute(expr))]
}

new_column(dat, z, x + y)

dat
#>        x     y     z
#>    <int> <int> <int>
#> 1:     1     5     6
#> 2:     2     6     8
#> 3:     3     7    10
#> 4:     4     8    12

reprex package (v2.0.1) 創建於 2022-03-01

或者使用match.call

library(data.table)
dat <- data.table(x = 1:4,
                  y = 5:8)

new_column <- function(df, col_name, expr) {
    fun_call <- match.call()
    df[, col_name := expr, 
       env = as.list(fun_call)[c('col_name', 'expr')]]
}

new_column(dat, z, x + y)

dat
#>        x     y     z
#>    <int> <int> <int>
#> 1:     1     5     6
#> 2:     2     6     8
#> 3:     3     7    10
#> 4:     4     8    12

reprex package (v2.0.1) 創建於 2022-03-01

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM