Функция 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() функция?

2 ответа

Решение

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

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

Что это делает, это сопоставить имена столбцов и подключить столбец к .,

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

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

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

Вы могли бы эквивалентно использовать комбинацию map() а также set_names() от мурлыкания

dat %>%
  map_df(sum, na.rm = TRUE) %>%
  set_names(paste0, "_new_name")
Другие вопросы по тегам