функция lapply с аргументами для фрейма данных и переменной

У меня есть настраиваемая функция, которая суммирует переменную. Я упростил функцию, чтобы проиллюстрировать свою проблему, т. е. она сложнее, чем показано ниже. Обратите внимание, что общая структура функции должна оставаться неизменной: она принимает аргумент для указания, с каким фреймом данных работать (df), и аргумент, переменную для суммирования (variable_to_test).

my_fun <- function(df, variable_to_test) {

  variable_to_test <- enquo(variable_to_test)
  new_var_name <- paste0(quo_name(variable_to_test), "_new_name")

  df %>% 
    summarise(
      !!new_var_name := sum(!!variable_to_test, na.rm = TRUE)
    ) 
}

Используя пример, я могу применить функцию к каждой переменной в моем фрейме данных:

library(tidyverse)
dat <- tibble(
  variable_1 = c(1:5, NA, NA, NA, NA, NA),
  variable_2 = c(NA, NA, NA, NA, NA, 11:15)
)


> my_fun(dat, variable_1)
# A tibble: 1 x 1
   variable_1_new_name
                 <int>
1                  15


> my_fun(dat, variable_2)
# A tibble: 1 x 1
  variable_2_new_name
                <int>
1                  65

Но: как я могу применить эту функцию ко всем столбцам в фрейме данных? Я пытался

> dat %>%
+ lapply(., my_fun)
Error in duplicate(quo) : argument "quo" is missing, with no default
Called from: duplicate(quo)

но это возвращает ошибку. Я борюсь с тем фактом, что функция принимает аргумент как для фрейма данных, так и для переменной для суммирования. Обратите внимание, что я хотел бы сохранить эту структуру - я считаю более элегантным передать имя фрейма данных в функцию вместо того, чтобы просто давать функции имя переменной и «жестко закодировать» фрейм данных в теле функции. Кто-нибудь знает, как lapply() эту функцию?


person piptoma    schedule 14.08.2017    source источник
comment
Вам нужно dplyr решение, или base R соответствует вашим потребностям? Обычно вы решаете эту проблему, предоставляя функции один статический и один переменный вход, например lapply(dat, function(x) myfun(dat, x)). Я не разбираюсь в dplyr, но может попробовать lapply(., function(x) myfun(., x))?   -  person LAP    schedule 14.08.2017
comment
У меня уже есть базовое решение R. Я попытался переписать функцию tidyeval-способом, так как это улучшает читаемость тела функции. Так что да, мне нужноtidyeval-решение :)   -  person piptoma    schedule 14.08.2017


Ответы (2)


О, я думаю, ты просто не на то строишь карту. Для решения tidyverse я бы попробовал:

map(dat, ~my_fun(dat, .))

Это сопоставляет имена столбцов и подключает столбец к ..

person Shorpy    schedule 14.08.2017

Вы работаете не на том уровне. Если вы сопоставляете функцию с фреймом данных, эта функция должна принимать столбец. Проблема здесь в том, что функция my_fun() ожидает фрейм данных, а не столбец.

Вам нужно найти другой способ решения проблемы. Одно из решений - использовать картографы, предоставляемые dplyr:

dat %>%
  summarise_all(sum, na.rm = TRUE) %>%
  rename_all(paste0, "_new_name")

Вы также можете использовать комбинацию map() и set_names() из purrr.

dat %>%
  map_df(sum, na.rm = TRUE) %>%
  set_names(paste0, "_new_name")
person Lionel Henry    schedule 14.08.2017