Dplyr для вычисления среднего, SD и отображения нескольких переменных

#r #dplyr

#r #dplyr

Вопрос:

У меня есть таблица со столбцами

[Время, var1, var2, var3, var4 … varN]

Мне нужно вычислить среднее / SE за раз для каждого var1, var2 … var n , и я хочу сделать это программно для всех переменных, а не по 1 за раз, что потребовало бы много копирования-вставки.

Раздел 8.2.3 здесь https://tidyeval.tidyverse.org/dplyr.html близко к тому, что я хочу, но мой приведенный ниже код:

 x <- as.data.frame(matrix(nrow = 2, ncol = 3))
x[1,1] = 1
x[1,2] = 2
x[1,3] = 3
x[2,1] =4
x[2,2] = 5
x[2,3] = 6
names(x)[1] <- "time"
names(x)[2] <- "var1"
names(x)[3] <- "var2"

grouped_mean3 <- function(.data, ...) {
  print(.data)
  summary_vars <- enquos(...)
  print(summary_vars)
  summary_vars <- purrr::map(summary_vars, function(var) {
    expr(mean(!!var, na.rm = TRUE))
  })
  print(summary_vars)

  .data %>%
    group_by(time)
    summarise(!!!summary_vars)  # Unquote-splice the list
}
grouped_mean3(x, var("var1"), var("var2"))
  

Дает

 Error in !summary_vars : invalid argument type
  

И первоначальной причиной является «Необходимо группировать по переменным, найденным в .data «. и он находит столбец, которого нет в фиктивном «x», который я сгенерировал для целей тестирования. К сожалению, я понятия не имею, что происходит.

Как мне на самом деле извлечь среднее значение из нового summary_vars и добавить его в таблицу .data? summary_vars становится чем-то вроде

 [[1]]
mean(~var1, na.rm = TRUE)

[[2]]
mean(~var2, na.rm = TRUE)
  

Что кажется близким, но требует оценки. Как мне это оценить? !!! не работал.

Для чего это стоит, я попытался подключить пример в dplyr к этому движку R. https://rdrr.io/cran/dplyr/man/starwars.html и это тоже не сработало.

Помочь?

Конечной целью будет таблица в виде

[Время, значение var1, значение var2, значение var3, значение var4 …]

Комментарии:

1. Ваш код выдаст другую ошибку, object 'summary_vars' not found . Пожалуйста, убедитесь, что ваш код действительно воспроизводим.

2. добавьте summary_vars <- enquos(...) в первую строку и удалите vars в вызове

3. Что-то вроде library(dplyr) data %>% group_by(Time) %>% summarise(across(var1:varN, mean))

4. @AbdessabourMtk Я добавил, что все еще вижу «Ошибка в!summary_vars: недопустимый тип аргумента». Однако пример обновлен.

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

Ответ №1:

Попробуйте это :

 library(dplyr)

grouped_mean3 <- function(.data, ...) {
  vars <- c(...)
  
  .data %>%
    group_by(time) %>%
    summarise(across(all_of(vars), mean))
}

grouped_mean3(x, 'var1')

#   time  var1mean
#  <dbl>     <dbl>
#1     1         2
#2     4         5

grouped_mean3(x, 'var1', 'var2')

#   time var1mean var2mean
#  <dbl>    <dbl>    <dbl>
#1     1        2        3
#2     4        5        6
  

Комментарии:

1. Спасибо — это приближает меня, но, к сожалению, я все еще кое-что не понимаю — этот код не дает мне таблицу со средними значениями, он выдает мне «x», когда я ее запускаю. x %>% group_by(time) %>% summary(mean_value = mean(var1)) Приведенная выше фраза найдет мне «среднее значение» var1 по времени. Я в основном пытаюсь выяснить, как сделать «var1» переменной, которую можно передавать (например, в виде строки), а затем таким образом я могу добавлять столбцы в исходный фрейм данных «x» из mean_var1, mean_var2, mean_var3…

2. @RNewbie Вы сохранили выходные данные в новой переменной? вот так x1 <- grouped_mean3(x, 'var1') , а затем проверьте x1 результаты. Если это работает не так, как задумано для вас, я бы предложил привести лучший пример и показать ожидаемый результат для него, чтобы мы знали, чего вы ожидаете.

3. FWIW это не решает мой первоначальный вопрос, но это: «x %>% group_by (time) %>% summarise_at(vars (names (x) [-1]), funs(mean(., na.rm = TRUE)))», кажется, дает мне все средства, которые яжелание. Итак, это начало.

4. @RNewbie Мой ответ действительно дает результат, аналогичный вашей конечной цели. Я обновил ответ, чтобы показать это. Если это не то, что вы хотите, вам нужно обновить свой пост с точным ожидаемым результатом и лучшими данными. Я не вижу никакого другого «оригинального вопроса» в вашем сообщении.

Ответ №2:

Возможно, это то, что вы ищете?

 x %>%
  group_by(time) %>%
  summarise_at(vars(starts_with('var')), ~mean(.,na.rm=T)) %>%
  rename_at(vars(starts_with('var')),funs(paste(.,"mean"))) %>%
  merge(x)
  

С вашими данными (из вашего вопроса) ниже приведен вывод:

   time var1mean var2mean var1 var2
1    1        2        3    2    3
2    4        5        6    5    6