在R中,我希望在基于变量 x
的运行对数据进行分组之后对其进行汇总(也就是说,每组数据对应于连续 x
值相同的数据的子集) . 例如,考虑以下数据框,我想在 x
的每次运行中计算平均 y
值:
(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 .
使用 tapply
在基础R中执行此分组操作很容易,传递 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'
为了完整性,我可以使用 cumsum
, head
和 tail
来重新实现 rle
运行ID来解决这个问题,但这会使分组代码更难以阅读并涉及到一些重新发明轮子:
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
是什么导致我的基于_1825158的分组代码在 dplyr
中失败,是否有任何解决方案使我能够在按运行ID分组时继续使用 rle
?
2 回答
一个选项似乎是使用
{}
,如:如果未来的dplyr版本也具有相当于data.table的
rleid
函数,那将是很好的 .我注意到使用
data.frame
或tbl_df
输入时会出现此问题,但使用tbl_dt
或data.table
输入时不会:我在dplyr的github页面上将其报告为issue .
如果你明确创建一个分组变量
g
它或多或少有效:我在这里使用了
transform
,因为mutate
会抛出错误 .