Самостоятельная функция с функциями dplyr не принимает значения аргументов

Я пытаюсь использовать mutate_at dplyr для вычитания значения числового столбца (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.

Этого я не понимаю, поскольку я просто вручную вызвал строку кода без функции, а мои столбцы числовые.

1
0
131
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я использовал это предложение, чтобы вычесть пары столбцов в списке фреймов данных. В моем примере всего 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]]))]
})
Ответ принят как подходящий

Виньетка Программирование с 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

Другие вопросы по теме