具有dplyr函数的自定义函数将不接受参数值

时间:2018-08-10 12:26:06

标签: r function dplyr mutate

我正在尝试使用dplyr的mutate_at从另一个对应的数字列(A1)中减去数字列的值(A2),我有多个列和多个数据帧想要为此做(BCDE ...,df1:df99),所以我想编写一个函数。

df1 <- df1 %>% mutate_at(.vars = vars(A1), .funs = funs(remainder = .-A2))

工作正常,但是当我尝试编写函数来执行此操作时:

REMAINDER <- function(df, numer, denom){ df <- df %>% mutate_at(.vars = vars(numer), .funs = funs(remainder = .-denom)) return(df) }

带有参数df1 <- REMAINDER(df1, A1, A2)

我收到错误Error in mutate_impl(.data, dots) : Evaluation error: non-numeric argument to binary operator.

我不理解,因为我只是手动调用没有功能的代码行,并且我的列都是数字。

2 个答案:

答案 0 :(得分:0)

小插图Programming with dplyr详细说明了怎么做:

library(dplyr)
REMAINDER <- function(df, numer, denom) {
  numer <- enquo(numer)
  denom <- enquo(denom)
  df %>% mutate_at(.vars = vars(!! numer), .funs = funs(remainder = . - !! denom))
}

df1 <- data_frame(A1 = 11:13, A2 = 3:1, B1 = 21:23, B2 = 8:6)

REMAINDER(df1, A1, A2)
# A tibble: 3 x 5
     A1    A2    B1    B2 remainder
  <int> <int> <int> <int>     <int>
1    11     3    21     8         8
2    12     2    22     7        10
3    13     1    23     6        12
REMAINDER(df1, B1, B2)
# A tibble: 3 x 5
     A1    A2    B1    B2 remainder
  <int> <int> <int> <int>     <int>
1    11     3    21     8        13
2    12     2    22     7        15
3    13     1    23     6        17

命名结果列

OP想要更新df1,他也希望将此操作应用于其他列。

不幸的是,当前定义的REMAINDER()函数将覆盖结果列:

df1
# A tibble: 3 x 4
     A1    A2    B1    B2
  <int> <int> <int> <int>
1    11     3    21     8
2    12     2    22     7
3    13     1    23     6
df1 <- REMAINDER(df1, A1, A2)
df1
# A tibble: 3 x 5
     A1    A2    B1    B2 remainder
  <int> <int> <int> <int>     <int>
1    11     3    21     8         8
2    12     2    22     7        10
3    13     1    23     6        12
df1 <- REMAINDER(df1, B1, B2)
df1
# A tibble: 3 x 5
     A1    A2    B1    B2 remainder
  <int> <int> <int> <int>     <int>
1    11     3    21     8        13
2    12     2    22     7        15
3    13     1    23     6        17

可以修改该函数,以便分别命名结果列:

REMAINDER <- function(df, numer, denom) {
  numer <- enquo(numer)
  denom <- enquo(denom)
  result_name <- paste0("remainder_", quo_name(numer), "_", quo_name(denom))
  df %>% mutate_at(.vars = vars(!! numer),
                   .funs = funs(!! result_name := . - !! denom))
}

现在,在不同的列上调用REMAINDER()两次,并在每次调用后替换df1,我们得到

df1 <- REMAINDER(df1, A1, A2)
df1 <- REMAINDER(df1, B1, B2)
df1
# A tibble: 3 x 6
     A1    A2    B1    B2 remainder_A1_A2 remainder_B1_B2
  <int> <int> <int> <int>           <int>           <int>
1    11     3    21     8               8              13
2    12     2    22     7              10              15
3    13     1    23     6              12              17

答案 1 :(得分:-1)

我已使用this suggestion来减去数据帧列表中的成对列。我的示例在两个数据帧中的每一个中只有3对列,并且可以使用更多的列和数据帧。

dt <- data.table(A1 = round(runif(3),1), A2 = round(runif(3),1),
                 B1 = round(runif(3),1), B2 = round(runif(3),1),
                 C1 =round(runif(3),1), C2 =round(runif(3),1))

dt = list(dt,dt+dt)

lapply(seq_along(dt), function(z) {
  dt[[z]][, lapply(1:(ncol(.SD)/2), function(x) (.SD[[2*x-1]] - .SD[[2*x]]))]
})