从载体中提取连续序列

时间:2015-01-13 23:02:30

标签: r sequence

我有一个名为v的向量,具有正值和负值以及零。问题是,如何提取(在列表中)所有连续的正数序列,即由零分隔的正数序列。

这是v:

v <- c(-75.09619, -38.31229,   0,  57.17792,  65.55923, 108.52735, 104.29929,  32.47125,0,   0,   0,   0, -26.65008, -49.48638, -79.60670,-90.55343, -34.60761,   0, 21.48842, 38.83820, 42.28727, 0)

输出必须是:

[1] 57.17792,  65.55923, 108.52735, 104.29929,  32.47125
[2] 21.48842 , 38.83820, 42.28727

有什么想法吗?

4 个答案:

答案 0 :(得分:15)

这是使用split的短篇文章:

split(v[v>0],cumsum(v==0)[v>0])
#$`1`
#[1]  57.17792  65.55923 108.52735 104.29929  32.47125
#
#$`6`
#[1] 21.48842 38.83820 42.28727

这基本上只是将v子集设置为正数,然后使用cumsum(v==0)计数器(在一组正值中保持稳定,并在紧随其后0时增加),split这个组。瞧!


使用rle的另一次尝试:

r <- rle(v>0)
start <- cumsum(r$lengths)[r$values] - r$lengths[r$values] + 1
end <- start + r$lengths[r$values] - 1
Map(function(start,end) v[start:end],start,end)

#[[1]]
#[1]  57.17792  65.55923 108.52735 104.29929  32.47125
#
#[[2]]
#[1] 21.48842 38.83820 42.28727

答案 1 :(得分:7)

您可以尝试:

indices <- which(v[v>=0]==0)
x <- Map(function(x,y) setdiff(v[v>=0][(y+1):(x-1)],0),
         indices[2:length(indices)],
         indices[1:(length(indices)-1)])
x[vapply(x,length,1L)>0]
#[[1]]
#[1]  57.17792  65.55923 108.52735 104.29929  32.47125
#[[2]]
#[1] 21.48842 38.83820 42.28727

我做了什么:

  • v
  • 的&gt; = 0值形成的向量中取出0位置
  • 使用Map函数,您可以在两个零之间提取向量的一部分
  • 最后一行的目的是从结果中去除没有值的序列(例如,如果原始向量中有两个或更多个零的序列)

答案 2 :(得分:6)

这里有一个选项:

ll <- split(v,cumsum(v==0))                      ## split data by 0 jump
ll <- lapply(ll,function(x){                     ## for each group 
  x <- x[x!=0]                                   ## remove null values   
  if(all(x>0) && length(x)>0)x else NA      ## check if all values are postifs
})
ll[!is.na(ll)]

# $`1`
# [1]  57.17792  65.55923 108.52735 104.29929  32.47125
# 
# $`6`
# [1] 21.48842 38.83820 42.28727

这个想法:

  1. 为每个0

  2. 创建一个组标识符
  3. 对于每个组删除0,检查所有值是否为positif,否则返回NA

  4. 从最终结果中删除缺失的向量。

  5. data.table解决方案

    最好将结果分组到data.table(data.frame)而不是列表中。我使用了相同的代码,只是将它包装在data.table结构中。

    library(data.table)
    A=data.table(v=v)
    A[,{x <- v[v!=0]
        if(all(x>0) && length(x)>0)x else NA_real_},
        cumsum(v==0)][!is.na(V1)]
    
    #     cumsum        V1
    # 1:      1  57.17792
    # 2:      1  65.55923
    # 3:      1 108.52735
    # 4:      1 104.29929
    # 5:      1  32.47125
    # 6:      6  21.48842
    # 7:      6  38.83820
    # 8:      6  42.28727
    

答案 3 :(得分:4)

我会在

中扔一个
v <- c(-75.09619, -38.31229,   0,  57.17792,  65.55923, 108.52735, 104.29929,  32.47125,0,   0,   0,   0, -26.65008, -49.48638, -79.60670,-90.55343, -34.60761,   0,21.48842, 38.83820, 42.28727, 0)


r <- rle(v > 0)
r <- r$lengths[r$values]

(pos <- v[v > 0])
# [1]  57.17792  65.55923 108.52735 104.29929  32.47125  21.48842  38.83820  42.28727



lapply(r, function(x) {
  out <- pos[1:x]
  pos <<- pos[-(1:x)]
  out
})

# [[1]]
# [1]  57.17792  65.55923 108.52735 104.29929  32.47125
# 
# [[2]]
# [1] 21.48842 38.83820 42.28727