我怎样用数据输入函数来制作一个函数

时间:2021-07-07 20:09:10

I faced a problem when exercising with data.table. Here is my problem. I wrote a simple subtraction function:

我在使用数据表进行锻炼时遇到了一个问题。这是我的问题。我写了一个简单的减法函数

minus <- function(a, b){
      return(a - b)
  }

My dataset is a simple data.table:

我的数据集是一个简单的数据集。

dt <- as.data.table(data.frame(first=c(5, 6, 7), second=c(1,2,3)))
dt
  first second
1     5      1
2     6      2
3     7      3

I would like to write another function,

我想写另一个函数,

myFunc <- function(dt, FUN, ...){
      return(dt[, new := FUN(...)])
  }

The usage is simply:

使用很简单:

res <- myFunc(dt, minus, first, second)

and the result would be the following:

其结果如下:

res
   first second new
1:     5      1   4
2:     6      2   4
3:     7      3   4

How can I archive such a goal? Thanks!

我怎样才能实现这样的目标呢?谢谢!

2 个解决方案

#1


2  

Maybe there's a better way, but you can try something like this:

也许有更好的方法,但是你可以试试这样的方法:

myFunc <- function(indt, FUN, ...) {
  FUN <- deparse(substitute(FUN))    # Get FUN as a string
  FUN <- match.fun(FUN)              # Match it to an existing function
  dots <- substitute(list(...))[-1]  # Get the rest of the stuff
  # I've used `copy(indt)` so that it doesn't affect your original dataset
  copy(indt)[, new := Reduce(FUN, mget(sapply(dots, deparse)))][]
}

(Note that this is very specific to how you've created your minus() function.)

(请注意,这对于如何创建减()函数非常特殊。)

Here it is in action:

它的行动如下:

res <- myFunc(dt, minus, first, second)
dt  ## Unchanged
#    first second
# 1:     5      1
# 2:     6      2
# 3:     7      3

res
#    first second new
# 1:     5      1   4
# 2:     6      2   4
# 3:     7      3   4

#2


0  

Here is a solution with do.call:

这里有一个解决方法。

myFunc <- function(dt, FUN, ...){
  arg.names <- as.character(match.call()[-(1:3)])
  copy(dt)[, "new" := do.call(FUN, lapply(arg.names, function(x) get(x)))]
}
#test
myFunc(dt, minus, first, second)
#   first second new
#1:     5      1   4
#2:     6      2   4
#3:     7      3   4

#1


2  

Maybe there's a better way, but you can try something like this:

也许有更好的方法,但是你可以试试这样的方法:

myFunc <- function(indt, FUN, ...) {
  FUN <- deparse(substitute(FUN))    # Get FUN as a string
  FUN <- match.fun(FUN)              # Match it to an existing function
  dots <- substitute(list(...))[-1]  # Get the rest of the stuff
  # I've used `copy(indt)` so that it doesn't affect your original dataset
  copy(indt)[, new := Reduce(FUN, mget(sapply(dots, deparse)))][]
}

(Note that this is very specific to how you've created your minus() function.)

(请注意,这对于如何创建减()函数非常特殊。)

Here it is in action:

它的行动如下:

res <- myFunc(dt, minus, first, second)
dt  ## Unchanged
#    first second
# 1:     5      1
# 2:     6      2
# 3:     7      3

res
#    first second new
# 1:     5      1   4
# 2:     6      2   4
# 3:     7      3   4

#2


0  

Here is a solution with do.call:

这里有一个解决方法。

myFunc <- function(dt, FUN, ...){
  arg.names <- as.character(match.call()[-(1:3)])
  copy(dt)[, "new" := do.call(FUN, lapply(arg.names, function(x) get(x)))]
}
#test
myFunc(dt, minus, first, second)
#   first second new
#1:     5      1   4
#2:     6      2   4
#3:     7      3   4