Подтвердить что ты не робот

Использование функций из нескольких столбцов в вызове dplyr mutate_at

Я хотел бы использовать функцию dplyr mutate_at чтобы применить функцию к нескольким столбцам в кадре данных, где функция вводит столбец, к которому она применяется, а также другой столбец в кадре данных.

В качестве конкретного примера, я бы посмотрел, чтобы изменить следующий фрейм данных

# Example input dataframe
df <- data.frame(
    x = c(TRUE, TRUE, FALSE),
    y = c("Hello", "Hola", "Ciao"),
    z = c("World", "ao", "HaOlam")
)

с вызовом mutate_at который выглядит примерно так

df %>%
mutate_at(.vars = vars(y, z),
          .funs = ifelse(x, ., NA))

вернуть фрейм данных, который выглядит примерно так

# Desired output dataframe
df2 <- data.frame(x = c(TRUE, TRUE, FALSE),
                  y_1 = c("Hello", "Hola", NA),
                  z_1 = c("World", "ao", NA))

Требуемый вызов mutate_at будет похож на следующий вызов mutate:

df %>%
   mutate(y_1 = ifelse(x, y, NA),
          z_1 = ifelse(x, z, NA))

Я знаю, что это может быть сделано в базе R несколькими способами, но я бы специально хотел достичь этой цели, используя функцию dplyr mutate_at для удобства чтения, взаимодействия с базами данных и т.д.

Ниже приведены некоторые аналогичные вопросы, задаваемые в stackoverflow, которые не относятся к вопросу, который я поставил здесь:

добавление нескольких столбцов в вызов dplyr mutate

dplyr :: mutate для добавления нескольких значений

Использование столбца внутри функции sum() с использованием функции dplyr mutate()

4b9b3361

Ответ 1

На этот вопрос ответил @eipi10 в комментарии @eipi10 по этому вопросу, но я пишу это здесь для потомков.

Решение здесь заключается в использовании:

df %>%
   mutate_at(.vars = vars(y, z),
             .funs = list(~ ifelse(x, ., NA)))

Использование list(~...) здесь указывает, что ifelse(x,., NA) является анонимной функцией, которая определяется в вызове mutate_at().

Это работает аналогично определению функции вне вызова mutate_at(), например так:

temp_fn <- function(input) ifelse(test = df[["x"]],
                                  yes = input,
                                  no = NA)

df %>%
   mutate_at(.vars = vars(y, z),
             .funs = temp_fn)

Примечание об изменениях синтаксиса в dplyr: до версии 0.8.0 dplyr вы просто писали .funs = funs(ifelse(x,., NA)), но функция funs() устарела и скоро будет удалена из dplyr,

Ответ 2

В дополнение к предыдущему ответу, если вы хотите, чтобы mutate_at() добавляла новые переменные (вместо замены) с именами, такими как z_1 и y_1 как в исходном вопросе, вам просто нужно добавить имя в funs(newname=...) вызов:

df %>%
  mutate_at(.vars = vars(y, z),
            .funs = funs('1'=ifelse(x, ., NA)))

Это дает:

# A tibble: 3 x 5
  x     y     z      y_1   z_1  
  <lgl> <chr> <chr>  <chr> <chr>
1 TRUE  Hello World  Hello World
2 TRUE  Hola  ao     Hola  ao   
3 FALSE Ciao  HaOlam NA    NA   

Дополнительные сведения и приемы см. В разделе: создание новых переменных с помощью mutate_at с сохранением исходных