提取向量中的第一个连续序列
Extract first continuous sequence in vector
我有一个向量:
as <- c(1,2,3,4,5,9)
我需要提取向量中的第一个连续序列,从索引 1 开始,输出如下:
1 2 3 4 5
是否有智能功能可以做到这一点,或者我必须做一些不太优雅的事情:
a <- c(1,2,3,4,5,9)
is_continunous <- c()
for (i in 1:length(a)) {
if(a[i+1] - a[i] == 1) {
is_continunous <- c(is_continunous, i)
} else {
break
}
}
continunous_numbers <- c()
if(is_continunous[1] == 1) {
is_continunous <- c(is_continunous, length(is_continunous)+1)
continunous_numbers <- a[is_continunous]
}
它确实有用,但我希望已经有一个函数可以做到这一点。
如果连续序列的索引仅从索引 1 或第一个序列开始,则不清楚您需要什么,无论起始索引是什么。
在这两种情况下,您都需要从检查相邻元素之间的差异开始:
d_as <- diff(as)
如果您只需要第一个序列从索引 1 开始:
if(d_as[1]==1) 1:(rle(d_as)$lengths[1]+1) else NULL
# [1] 1 2 3 4 5
rle
允许知道相同值的每个连续序列的长度和值。
如果需要第一个连续的序列,不管起始索引是什么:
rle_d_as <- rle(d_as)
which(d_as==1)[1]+(0:(rle_d_as$lengths[rle_d_as$values==1][1]))
示例(第二个选项):
as <- c(1,2,3,4,5,9)
d_as <- diff(as)
rle_d_as <- rle(d_as)
which(d_as==1)[1]+(0:(rle_d_as$lengths[rle_d_as$values==1][1]))
#[1] 1 2 3 4 5
as <- c(4,3,1,2,3,4,5,9)
d_as <- diff(as)
rle_d_as <- rle(d_as)
which(d_as==1)[1]+(0:(rle_d_as$lengths[rle_d_as$values==1][1]))
# [1] 3 4 5 6 7
as <- c(1, 2, 3, 6, 7, 8)
d_as <- diff(as)
rle_d_as <- rle(d_as)
which(d_as==1)[1]+(0:(rle_d_as$lengths[rle_d_as$values==1][1]))
# [1] 1 2 3
捕获序列的一个简单方法是找到向量的 diff
并获取所有带有 diff == 1
的元素加上下一个元素,即
d1<- which(diff(as) == 1)
as[c(d1, d1[length(d1)]+1)]
注意
这仅适用于您的向量中只有一个序列的情况。但是,如果我们想让它更通用,那么我建议创建一个函数,
get_seq <- function(vec){
d1 <- which(diff(as) == 1)
if(all(diff(d1) == 1)){
return(c(d1, d1[length(d1)]+1))
}else{
d2 <- split(d1, cumsum(c(1, diff(d1) != 1)))[[1]]
return(c(d2, d2[length(d2)]+1))
}
}
#testing it
as <- c(3, 5, 1, 2, 3, 4, 9, 7, 5, 4, 5, 6, 7, 8)
get_seq(as)
#[1] 3 4 5 6
as <- c(8, 9, 10, 11, 1, 2, 3, 4, 7, 8, 9, 10)
get_seq(as)
#[1] 1 2 3 4
as <- c(1, 2, 3, 4, 5, 6, 11)
get_seq(as)
#[1] 1 2 3 4 5 6
我有一个向量:
as <- c(1,2,3,4,5,9)
我需要提取向量中的第一个连续序列,从索引 1 开始,输出如下:
1 2 3 4 5
是否有智能功能可以做到这一点,或者我必须做一些不太优雅的事情:
a <- c(1,2,3,4,5,9)
is_continunous <- c()
for (i in 1:length(a)) {
if(a[i+1] - a[i] == 1) {
is_continunous <- c(is_continunous, i)
} else {
break
}
}
continunous_numbers <- c()
if(is_continunous[1] == 1) {
is_continunous <- c(is_continunous, length(is_continunous)+1)
continunous_numbers <- a[is_continunous]
}
它确实有用,但我希望已经有一个函数可以做到这一点。
如果连续序列的索引仅从索引 1 或第一个序列开始,则不清楚您需要什么,无论起始索引是什么。
在这两种情况下,您都需要从检查相邻元素之间的差异开始:
d_as <- diff(as)
如果您只需要第一个序列从索引 1 开始:
if(d_as[1]==1) 1:(rle(d_as)$lengths[1]+1) else NULL
# [1] 1 2 3 4 5
rle
允许知道相同值的每个连续序列的长度和值。
如果需要第一个连续的序列,不管起始索引是什么:
rle_d_as <- rle(d_as)
which(d_as==1)[1]+(0:(rle_d_as$lengths[rle_d_as$values==1][1]))
示例(第二个选项):
as <- c(1,2,3,4,5,9)
d_as <- diff(as)
rle_d_as <- rle(d_as)
which(d_as==1)[1]+(0:(rle_d_as$lengths[rle_d_as$values==1][1]))
#[1] 1 2 3 4 5
as <- c(4,3,1,2,3,4,5,9)
d_as <- diff(as)
rle_d_as <- rle(d_as)
which(d_as==1)[1]+(0:(rle_d_as$lengths[rle_d_as$values==1][1]))
# [1] 3 4 5 6 7
as <- c(1, 2, 3, 6, 7, 8)
d_as <- diff(as)
rle_d_as <- rle(d_as)
which(d_as==1)[1]+(0:(rle_d_as$lengths[rle_d_as$values==1][1]))
# [1] 1 2 3
捕获序列的一个简单方法是找到向量的 diff
并获取所有带有 diff == 1
的元素加上下一个元素,即
d1<- which(diff(as) == 1)
as[c(d1, d1[length(d1)]+1)]
注意
这仅适用于您的向量中只有一个序列的情况。但是,如果我们想让它更通用,那么我建议创建一个函数,
get_seq <- function(vec){
d1 <- which(diff(as) == 1)
if(all(diff(d1) == 1)){
return(c(d1, d1[length(d1)]+1))
}else{
d2 <- split(d1, cumsum(c(1, diff(d1) != 1)))[[1]]
return(c(d2, d2[length(d2)]+1))
}
}
#testing it
as <- c(3, 5, 1, 2, 3, 4, 9, 7, 5, 4, 5, 6, 7, 8)
get_seq(as)
#[1] 3 4 5 6
as <- c(8, 9, 10, 11, 1, 2, 3, 4, 7, 8, 9, 10)
get_seq(as)
#[1] 1 2 3 4
as <- c(1, 2, 3, 4, 5, 6, 11)
get_seq(as)
#[1] 1 2 3 4 5 6