使用函数的字符名称和参数作为字符向量将函数应用于 data.table
Apply function to data.table using function's character name and arguments as character vector
我想在 data.table 上通过字符名称调用函数。每个函数还有一个参数向量(因此有一长串函数可以应用于 data.table)。参数是 data.table 列。我的第一个想法是 do.call 将是完成该任务的好方法。这是一个简单的示例,其中一个函数名称为 运行 并且它是要传递的列向量:
# set up dummy data
set.seed(1)
DT <- data.table(x = rep(c("a","b"),each=5), y = sample(10), z = sample(10))
# columns to use as function arguments
mycols <- c('y','z')
# function name
func <- 'sum'
# my current solution:
DT[, do.call(func, list(get('y'), get('z'))), by = x]
# x V1
# 1: a 47
# 2: b 63
我对此不满意,因为它需要具体命名每一列。我只想传递一个字符向量 mycols
。
在这种情况下,我需要的其他解决方案是:
DT[, do.call(func, .SD), .SDcols = mycols, by = x]
但是自定义函数有点问题,唯一对我有用的解决方案是第一个:
#own dummy function
myfunc <- function(arg1, arg2){
arg1+arg2
}
func <- 'myfunc'
DT[, do.call(func, list(get('y'), get('z'))), by = x]
# x V1
# 1: a 6
# 2: a 6
# 3: a 11
# 4: a 17
# 5: a 7
# 6: b 15
# 7: b 17
# 8: b 10
# 9: b 11
# 10: b 10
# second solution does not work
DT[, do.call(func, .SD), .SDcols = mycols, by = x]
# Error in myfunc(y = c(3L, 4L, 5L, 7L, 2L), z = c(3L, 2L, 6L, 10L, 5L)) :
# unused arguments (y = c(3, 4, 5, 7, 2), z = c(3, 2, 6, 10, 5))
据我了解,它假设 myfunc 有参数 y, z
这是不正确的。应该有变量 y,z
应该传递给参数 arg1, arg2
.
我也试过 mget 函数,但也没有成功:
DT[, do.call(func, mget(mycols)), by = x]
# Error: value for ‘y’ not found
我可能遗漏了一些相当明显的东西,在此先感谢您的指导。
这可能取决于您要使用的函数类型,但您似乎 Reduce
可能感兴趣。
这是你的两个例子:
mycols <- c('y','z')
func <- 'sum'
DT[, Reduce(func, mget(mycols)), by = x]
# x V1
# 1: a 47
# 2: b 63
myfunc <- function(arg1, arg2){
arg1+arg2
}
func <- 'myfunc'
DT[, Reduce(func, mget(mycols)), by = x]
# x V1
# 1: a 6
# 2: a 6
# 3: a 11
# 4: a 17
# 5: a 7
# 6: b 15
# 7: b 17
# 8: b 10
# 9: b 11
# 10: b 10
这是一个帮助我实现我想要的解决方案。
func <- 'sum'
mycols <- c('y','z')
DT[, do.call(func, lapply(mycols, function(x) get(x))), by = x]
# x V1
# 1: a 47
# 2: b 63
可以向其传递 base
函数或自定义函数(不像 Reduce
解决方案那么具体)。
是的,您遗漏了一些东西(好吧,它不是很明显,但仔细调试错误可以确定问题所在)。您的函数需要命名参数 arg1
和 arg2
。您正在通过 do.call
向其传递参数 y = ...
和 z = ...
(您已经注意到)。解决方案是传递没有名称的列表:
> DT[, do.call(func, unname(.SD[, mycols, with = F])), by = x]
x V1
1: a 6
2: a 6
3: a 11
4: a 17
5: a 7
6: b 15
7: b 17
8: b 10
9: b 11
10: b 10
我想在 data.table 上通过字符名称调用函数。每个函数还有一个参数向量(因此有一长串函数可以应用于 data.table)。参数是 data.table 列。我的第一个想法是 do.call 将是完成该任务的好方法。这是一个简单的示例,其中一个函数名称为 运行 并且它是要传递的列向量:
# set up dummy data
set.seed(1)
DT <- data.table(x = rep(c("a","b"),each=5), y = sample(10), z = sample(10))
# columns to use as function arguments
mycols <- c('y','z')
# function name
func <- 'sum'
# my current solution:
DT[, do.call(func, list(get('y'), get('z'))), by = x]
# x V1
# 1: a 47
# 2: b 63
我对此不满意,因为它需要具体命名每一列。我只想传递一个字符向量 mycols
。
在这种情况下,我需要的其他解决方案是:
DT[, do.call(func, .SD), .SDcols = mycols, by = x]
但是自定义函数有点问题,唯一对我有用的解决方案是第一个:
#own dummy function
myfunc <- function(arg1, arg2){
arg1+arg2
}
func <- 'myfunc'
DT[, do.call(func, list(get('y'), get('z'))), by = x]
# x V1
# 1: a 6
# 2: a 6
# 3: a 11
# 4: a 17
# 5: a 7
# 6: b 15
# 7: b 17
# 8: b 10
# 9: b 11
# 10: b 10
# second solution does not work
DT[, do.call(func, .SD), .SDcols = mycols, by = x]
# Error in myfunc(y = c(3L, 4L, 5L, 7L, 2L), z = c(3L, 2L, 6L, 10L, 5L)) :
# unused arguments (y = c(3, 4, 5, 7, 2), z = c(3, 2, 6, 10, 5))
据我了解,它假设 myfunc 有参数 y, z
这是不正确的。应该有变量 y,z
应该传递给参数 arg1, arg2
.
我也试过 mget 函数,但也没有成功:
DT[, do.call(func, mget(mycols)), by = x]
# Error: value for ‘y’ not found
我可能遗漏了一些相当明显的东西,在此先感谢您的指导。
这可能取决于您要使用的函数类型,但您似乎 Reduce
可能感兴趣。
这是你的两个例子:
mycols <- c('y','z')
func <- 'sum'
DT[, Reduce(func, mget(mycols)), by = x]
# x V1
# 1: a 47
# 2: b 63
myfunc <- function(arg1, arg2){
arg1+arg2
}
func <- 'myfunc'
DT[, Reduce(func, mget(mycols)), by = x]
# x V1
# 1: a 6
# 2: a 6
# 3: a 11
# 4: a 17
# 5: a 7
# 6: b 15
# 7: b 17
# 8: b 10
# 9: b 11
# 10: b 10
这是一个帮助我实现我想要的解决方案。
func <- 'sum'
mycols <- c('y','z')
DT[, do.call(func, lapply(mycols, function(x) get(x))), by = x]
# x V1
# 1: a 47
# 2: b 63
可以向其传递 base
函数或自定义函数(不像 Reduce
解决方案那么具体)。
是的,您遗漏了一些东西(好吧,它不是很明显,但仔细调试错误可以确定问题所在)。您的函数需要命名参数 arg1
和 arg2
。您正在通过 do.call
向其传递参数 y = ...
和 z = ...
(您已经注意到)。解决方案是传递没有名称的列表:
> DT[, do.call(func, unname(.SD[, mycols, with = F])), by = x]
x V1
1: a 6
2: a 6
3: a 11
4: a 17
5: a 7
6: b 15
7: b 17
8: b 10
9: b 11
10: b 10