В R я хочу обобщить свои данные после группировки на основе прогонов переменной x
(так как каждая группа данных соответствует подмножеству данных, где последовательные значения x
совпадают). Например, рассмотрим следующий фрейм данных, где я хочу вычислить среднее значение y
в каждом прогоне x
:
(dat <- data.frame(x=c(1, 1, 1, 2, 2, 1, 2), y=1:7))
# x y
# 1 1 1
# 2 1 2
# 3 1 3
# 4 2 4
# 5 2 5
# 6 1 6
# 7 2 7
В этом примере переменная x
имеет пробеги длиной 3, затем 2, затем 1 и, наконец, 1, принимая значения 1, 2, 1 и 2 в этих четырех прогонах. Соответствующим средством y
в этих группах являются 2, 4.5, 6 и 7.
Легко выполнить эту сгруппированную операцию в базе R с помощью tapply
, передав dat$y
в качестве данных, используя rle
для вычисления номера прогона из dat$x
и передачи нужной итоговой функции:
tapply(dat$y, with(rle(dat$x), rep(seq_along(lengths), lengths)), mean)
# 1 2 3 4
# 2.0 4.5 6.0 7.0
Я решил, что смогу довольно быстро перенести эту логику в dplyr, но мои попытки до сих пор закончились ошибками:
library(dplyr)
# First attempt
dat %>%
group_by(with(rle(x), rep(seq_along(lengths), lengths))) %>%
summarize(mean(y))
# Error: cannot coerce type 'closure' to vector of type 'integer'
# Attempt 2 -- maybe "with" is the problem?
dat %>%
group_by(rep(seq_along(rle(x)$lengths), rle(x)$lengths)) %>%
summarize(mean(y))
# Error: invalid subscript type 'closure'
Для полноты я мог бы повторно реализовать идентификатор запуска rle
, используя cumsum
, head
и tail
, чтобы обойти это, но это делает код группировки более жестким для чтения и требует немного переосмысления колесо:
dat %>%
group_by(run=cumsum(c(1, head(x, -1) != tail(x, -1)))) %>%
summarize(mean(y))
# run mean(y)
# (dbl) (dbl)
# 1 1 2.0
# 2 2 4.5
# 3 3 6.0
# 4 4 7.0
Что приводит к тому, что мой код rle
на основе rle
не работает в dplyr
, и существует ли какое-либо решение, которое позволяет мне продолжать использовать rle
при группировке по идентификатору запуска?