当前位置:  开发笔记 > 编程语言 > 正文

将(1:n)[boolean]分割成连续的序列

如何解决《将(1:n)[boolean]分割成连续的序列》经验,为你挑选了1个好方法。

我想将我的数据分成连续行的组,通过一些测试.这是一个例子:

set.seed(1)
n   <-  29
ok  <-  sample(c(TRUE,FALSE),n,replace=TRUE,prob=c(.7,.3))

vec <- (1:n)[ok]
# [1]  1  2  3  5  8  9 10 11 12 13 14 16 19 22 23 24 25 26 27 28

所需的输出是"vec"分组为连续序列:

out <- list(1:3,5,8:14,16,19,22:28)

这有效:

nv  <- length(vec)

splits <- 1 + which(diff(vec) != 1)
splits <- c(1,splits,nv+1)
nsp    <- length(splits)

out <- list()
for (i in 1:(nsp-1)){
    out[[i]] <- vec[splits[i]:(splits[i+1]-1)]
}

我猜测基地R有一个更清洁的方式...?我还不熟悉我在SO上看过的那些rlecumsum诡计......



1> eddi..:

这是cumsum给你的"诀窍":

split(vec, cumsum(c(1, diff(vec)) - 1))

更新

以下是使用您的版本的简单示例,split(vec, cumsum(c(0, diff(vec) > 1)))其中每个步骤都已细分:

vec <- c(1:3,7:9)            #  1 2 3 7 8 9 (sample with two contiguous sequences)
diff(vec)                    #   1 1 4 1 1  (lagged difference)
diff(vec) > 1                #   F F T F F  (not contiguous where diff > 1)
                             #   0 0 1 0 0  (numeric equivalent for T/F)
c(0, diff(vec) > 1)          #  0 0 0 1 0 0 (pad with 0 to align with original vector)
cumsum(c(0, diff(vec) > 1))  #  0 0 0 1 1 1 (cumulative sum of logical values)

groups <- cumsum(c(0, diff(vec) > 1)) #  0 0 0 1 1 1

sets <- split(vec, groups) # split into groups named by cumulative sum

sets
# $`0`
# [1] 1 2 3
# 
# $`1`
# [1] 7 8 9

然后如果你想出于某种原因输出它:

# Create strings representing each contiguous range
set_strings <- sapply(sets, function(x) paste0(min(x),":",max(x)))

set_strings
#     0     1
# "1:3" "7:9"

# Print out a concise representation of all contiguous sequences
print(paste0(set_strings,collapse=","))

# [1] "1:3,7:9"

推荐阅读
小色米虫_524
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有