19

在 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。这些组中的相应均值是y2、4.5、6 和 7。

在基础 R 中使用 、作为数据tapply传递、使用从 计算运行次数并传递所需的汇总函数很容易执行此分组操作:dat$yrledat$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运行 id来解决这个问题,但它使分组代码更难阅读,并且涉及到一些重新发明轮子:cumsumheadtail

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的 -based 分组代码失败,是否有任何解决方案可以让我在按运行 id 分组时dplyr继续使用?rle

4

2 回答 2

13

一种选择似乎是使用{}as :

dat %>%
    group_by(yy = {yy = rle(x); rep(seq_along(yy$lengths), yy$lengths)}) %>%
    summarize(mean(y))
#Source: local data frame [4 x 2]
#
#     yy mean(y)
#  (int)   (dbl)
#1     1     2.0
#2     2     4.5
#3     3     6.0
#4     4     7.0

如果未来的 dplyr 版本也有相当于 data.table 的rleid功能,那就太好了。


我注意到在使用 or 输入时会出现此问题,但在使用data.frameortbl_df输入时不会:tbl_dtdata.table

dat %>% 
    tbl_df %>% 
    group_by(yy = with(rle(x), rep(seq_along(lengths), lengths))) %>%
    summarize(mean(y))
Error: cannot coerce type 'closure' to vector of type 'integer'

dat %>% 
    tbl_dt %>% 
    group_by(yy = with(rle(x), rep(seq_along(lengths), lengths))) %>%
    summarize(mean(y))
Source: local data table [4 x 2]

     yy mean(y)
  (int)   (dbl)
1     1     2.0
2     2     4.5
3     3     6.0
4     4     7.0

我在 dplyr 的 github 页面上报告了这个问题。

于 2016-02-10T11:03:57.400 回答
2

如果您显式创建一个分组变量g,它或多或少会起作用:

> dat %>% transform(g=with(rle(dat$x),{ rep(seq_along(lengths), lengths)}))%>%                                   
 group_by(g) %>% summarize(mean(y))
Source: local data frame [4 x 2]

      g mean(y)
  (int)   (dbl)
1     1     2.0
2     2     4.5
3     3     6.0
4     4     7.0

transform在这里使用是因为mutate会引发错误。

于 2016-02-06T22:07:52.220 回答