我正在使用R中的一个列表,它看起来像这样
[1] 0 0 4 4 0 4 0现在假设我想生成一个与这个列表相对应的数字列表,如下所示
[[1]]
[1] 1 1
[[2]]
[1] 2 2
[[3]]
[1] 3 6
[[4]]
[1] 7 10
[[5]]
[1] 11 11
[[6]]
[1] 12 15
[[7]]
[1] 16 16换句话说,第一个列表给出了一个从1到16的数字序列列表中的组,第二个列表给出了每个组的开始和结束。
如果考虑序列,这可能更容易理解
1 2 3-6 7-10 11 12-15 16
有什么简单的方法可以做到这一点吗?我想我可以使用某种全局索引和lapply来做这件事,但我想看看是否有更简单的方法。
发布于 2015-08-27 03:22:31
这里有一种方法
# alternate input suggested by @MichaelChirico
d = c(0,0,3,3,0,3,0)
# my preferred approach
library(data.table) # version 1.9.5+
Map(c,
seq_along(d)+shift(cumsum(d), type="lag", fill=0),
seq_along(d)+cumsum(d)
)@akrun也有类似的变化:
# alternate input, starting from OP's
d2 = c(0, 0, 4, 4, 0, 4, 0)
d2 = replace( d2, !d2, 1)
# @akrun's answer
Map(c, cumsum(d2)-d2+1, cumsum(d2))还有更多:
# my original answer
start = c(1,head(cumsum(d+1)+1,-1))
Map(c, start, start + d)
# another way
s = sequence(d+1)
Map(c, seq_along(s)[s==1], seq_along(s)[c(diff(s) < 1, TRUE)] )发布于 2015-08-27 03:30:13
这里有一个稍微不同的方法:
x <- c(0,0,3,3,0,3,0)
f <- function(x) {
ee <- split(seq_len(sum(x+1)), rep.int(seq_along(x), x+1))
lapply(ee, range)
}
f(x)发布于 2015-08-27 03:26:41
这是一个可以做到这一点的函数,远不及@Frank的答案那么优雅:
mygenerator <- function(vec){
counter <- 1
outlist <- list()
for(i in 1:length(vec)){
if(vec[i] == 0){
outlist[[i]] <- c(counter, counter)
counter <- counter + 1
} else {
outlist[[i]] <- c(counter, counter + vec[i] - 1)
counter <- counter + vec[i]
}
}
outlist
}
mygenerator(c(0, 0, 4, 4, 0, 4, 0))
[[1]]
[1] 1 1
[[2]]
[1] 2 2
[[3]]
[1] 3 6
[[4]]
[1] 7 10
[[5]]
[1] 11 11
[[6]]
[1] 12 15
[[7]]
[1] 16 16https://stackoverflow.com/questions/32234849
复制相似问题