[英]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 by
, rlang
有一種通用的延遲評估的方法,即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.