Суммируйте множество переменных с функцией двух переменных

#r #dplyr

Вопрос:

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

 df <- as_tibble(iris)
df %>% summarise_if(is.numeric, .fun = mean)
 

Это прекрасно работает. Но предположим теперь , что функция in .fun включает в себя 2 аргумента из набора данных (примером может служить weighet.mean , где весовой переменной является Sepal.Длина). Я пытался,

 df %>% summarise_if(is.numeric, .fun = function(x, w) weighted.mean(x, w), w = Sepal.Length)
 

Ошибка заключалась в

Ошибка в списке 2(…) : объект ‘разделен.Ширина» не найдена

Я подозреваю, что R искал не Sepal.Length в df глобальной среде, а в ней. Поэтому я должен использовать,

 df %>% summarise_if(is.numeric, .fun = function(x, w) weighted.mean(x, w), w = df$Sepal.Length)
 

Это работает, но это не очень хорошо, чтобы делать df$Sepal.Длина. Например, для меня становится совершенно невозможным вычислить средневзвешенное значение по группам.

 df %>% group_by(Species) %>% summarise_if(is.numeric, .fun = function(x, w) weighted.mean(x, w), w = df$Sepal.Length)
 

Ошибка: Проблема с summarise() колонкой Sepal.Length .
Sepal.Length = (function (x, w) ... .
x ‘x’ и » w » должны иметь одинаковую длину
ℹ Ошибка произошла в группе 1: Вид = сетоза.

Итак, как использовать summarise_if или summarise_at с функциями, включающими две переменные из набора данных.

Ответ №1:

Если нам нужно использовать Sepal.Length as w , объедините ( c ) вывод where(is.numeric) и укажите -Sepal.Length , из чего следует удалить столбец across , а затем используйте weighted.mean для других числовых столбцов с w помощью as ‘Sepal.Длина’

 library(dplyr)
df %>% 
   summarise(across(c(where(is.numeric), -Sepal.Length), 
        ~ weighted.mean(., w = Sepal.Length)))
# A tibble: 1 × 3
  Sepal.Width Petal.Length Petal.Width
        <dbl>        <dbl>       <dbl>
1        3.05         3.97        1.29
 

Или сгруппированный был бы

 df %>%
   group_by(Species) %>% 
   summarise(across(c(where(is.numeric), -Sepal.Length), 
        ~ weighted.mean(., w = Sepal.Length)))
 

-выход

 # A tibble: 3 × 4
  Species    Sepal.Width Petal.Length Petal.Width
  <fct>            <dbl>        <dbl>       <dbl>
1 setosa            3.45         1.47       0.248
2 versicolor        2.78         4.29       1.34 
3 virginica         2.99         5.60       2.03 
 

ПРИМЕЧАНИЕ: _if , _at , _all функции суффиксов устарели в пользу across

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

1. Большое спасибо. Я не знал, и я все еще использую их. Просто вопрос, почему — перед сепалом.длина

2. @Ari.stat просто для того, чтобы удалить этот столбец из взвешенного значения.в противном случае и x, и w будут разделены. Длина для этого столбца

3. Что, если мне снова понадобится третья переменная-имя?

4. то есть df %>% group_by(Species) %>% summarise(across(c(where(is.numeric), -c(Sepal.Length, Sepal.Width)), ~ weighted.mean(., w = Sepal.Length)))

5. Или это может быть вектор имен, т. е. nm1 <- names(df)[1:2];df %>% group_by(Species) %>% summarise(across(c(where(is.numeric), -all_of(nm1)), ~ weighted.mean(., w = Sepal.Length)))