dplyr подводит итог, когда функция возврата имеет векторное значение?

dplyr::summarize() Функция может применять к данным произвольные функции, но кажется, что функция должна возвращать скалярное значение. Мне любопытно, есть ли разумный способ обработки функций, которые возвращают векторное значение, не делая многократных вызовов функции.

Вот несколько глупый минимальный пример. Рассмотрим функцию, которая дает несколько значений, например:

f <- function(x,y){
  coef(lm(x ~ y, data.frame(x=x,y=y)))
}

и данные, которые выглядят так:

df <- data.frame(group=c('A','A','A','A','B','B','B','B','C','C','C','C'), x=rnorm(12,1,1), y=rnorm(12,1,1))

Я хотел бы сделать что-то вроде:

df %>% 
group_by(group) %>%
summarise(f(x,y))

и получить таблицу, в которую добавлено 2 столбца для каждого возвращаемого значения вместо обычного 1 столбца. Вместо этого это ошибки с:Expecting single value

Конечно, мы можем получить несколько значений изdlpyr::summarise() давая аргумент функции несколько раз:

f1 <- function(x,y) coef(lm(x ~ y, data.frame(x=x,y=y)))[[1]]
f2 <- function(x,y) coef(lm(x ~ y, data.frame(x=x,y=y)))[[2]]

df %>% 
group_by(group) %>%
summarise(a = f1(x,y), b = f2(x,y))

Это дает желаемый результат:

  group         a            b
1     A 1.7957245 -0.339992915
2     B 0.5283379 -0.004325209
3     C 1.0797647 -0.074393457

но кодирование таким образом смехотворно грубо и безобразно.

data.table обрабатывает этот случай более кратко:

dt <- as.data.table(df)
dt[, f(x,y), by="group"]

но создает вывод, который расширяет таблицу, используя дополнительные строки вместо дополнительных столбцов, что приводит к выводу, который является и запутанным, и с которым труднее работать:

 group           V1
1:     A  1.795724536
2:     A -0.339992915
3:     B  0.528337890
4:     B -0.004325209
5:     C  1.079764710
6:     C -0.074393457

Конечно, есть более классическиеapply стратегии, которые мы могли бы использовать здесь,

sapply(levels(df$group), function(x) coef(lm(x~y, df[df$group == x, ])))


                     A            B           C
(Intercept)  1.7957245  0.528337890  1.07976471
y           -0.3399929 -0.004325209 -0.07439346

но это приносит в жертву и элегантность, и я подозреваю, что скорость группировки. В частности, обратите внимание, что мы не можем использовать нашу предопределенную функциюf в этом случае, но придется жестко закодировать группировку в определение функции.

Есть лиdplyr функция для обработки этого случая? Если нет, то существует ли более элегантный способ обработки этого процесса оценки вектор-функций по data.frame по группам?

Ответы на вопрос(2)

Ваш ответ на вопрос