使用 := 将 data.table 列名传递给函数
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)
现在我想为任何给定函数创建一个新列:
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-idiomatic的方式。如果您需要做其他事情,例如使用 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 创建
此问题 data.table 等同于 Pass a data.frame column name to a function。
假设我有一个非常简单的 data.table:
dat <- data.table(x = 1:4,
y = 5:8)
现在我想为任何给定函数创建一个新列:
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-idiomatic的方式。如果您需要做其他事情,例如使用 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 创建