沿着矢量搜索并计算平均值

5

我有一些数据,看起来像这样:

require(data.table)
DT <- data.table(x=c(19,19,19,21,21,19,19,22,22,22),
             y=c(53,54,55,32,44,45,49,56,57,58))

我希望能够沿着x轴搜索,并计算y的平均值。但是,在使用时。
DT[, .(my=mean(y)), by=.(x)]

我会为 x 的重叠值得到总体平均值。 我想要沿着 x 进行搜索,并且每次 x 改变时,都想计算一个新的平均值。对于所提供的示例,输出将是:

DTans <- data.table(x=c(19,21,19,22),
             my=c(54,38,47,57))
3个回答

10
我们可以使用 rleid 创建另一个分组变量,获取 'y' 的 mean 值,并将 'indx' 分配为 NULL。
library(data.table) # v 1.9.5+
DT[, .(my = mean(y)), by = .(indx = rleid(x), x)][, indx := NULL]
#    x my
#1: 19 54
#2: 21 38
#3: 19 47
#4: 22 57

基准测试

set.seed(24)
foo <- function(x) sample(x, 1e7L, replace = TRUE)
DT  <- data.table(x = foo(100L), y = foo(10000L))

josilber <- function() {
    new.group <- c(1, diff(DT$x) != 0)
    res <- data.table(x = DT$x[new.group == 1], 
              my = tapply(DT$y, cumsum(new.group), mean))
}

Roland <- function() {
    DT[, .(my = mean(y), x = x[1]), by = cumsum(c(1, diff(x) != 0))]
}

akrun <- function() { 
    DT[, .(my = mean(y)), by = .(indx = rleid(x), x)][,indx := NULL]
}

bgoldst <- function() {
    with(rle(DT$x), data.frame(x = values, 
       my = tapply(DT$y, rep(1:length(lengths), lengths), mean)))
}

system.time(josilber())
#   user  system elapsed 
#159.405   1.759 161.110 

system.time(bgoldst())
#   user  system elapsed 
#162.628   0.782 163.380 

system.time(Roland())
#   user  system elapsed 
# 18.633   0.052  18.678 

system.time(akrun())
#   user  system elapsed 
# 1.242   0.003   1.246 

2
喜欢基准测试(有意义的数据大小和时间)! - Arun
@Arun 感谢您的评论。 - akrun

3
您可以识别连续元素的组,并为每个组识别平均值和值:
(new.group <- c(1, diff(DT$x) != 0))
# [1] 1 0 0 1 0 1 0 1 0 0
DT[, list(x = x[1L], my = mean(y)), by = list(indx = cumsum(new.group))]
#    indx  x my
# 1:    1 19 54
# 2:    2 21 38
# 3:    3 19 47
# 4:    4 22 57

2
data.tabletapply混合使用?简直是亵渎! - Roland
我对data.table的了解太少了,以至于我甚至不知道这是多么亵渎!在获得new.group后,有没有一种简单的方法来对DT进行分组? - josliber
更重要的是,它很慢。这可能是一种可能性:DT[, .(my = mean(y), x = x[1]), by = cumsum(c(1, diff(x) != 0))],但如果您可以使用1.9.5,显然akrun的答案更好。 - Roland
@Roland 这是开发版本吗?我试图进行基准测试,但 CRAN 只有 1.9.4 版本。 - josliber
@josilber,是的,1.9.5在Github上进行开发。 - Arun

3
with(rle(DT$x),data.frame(x=values,my=tapply(DT$y,rep(1:length(lengths),lengths),mean)));
##    x my
## 1 19 54
## 2 21 38
## 3 19 47
## 4 22 57

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接