【问题标题】:Group integer vector into consecutive runs将整数向量分组为连续运行
【发布时间】:2018-11-04 21:41:59
【问题描述】:

我有两个整数向量。我想确定第二个向量中以第一个向量为条件的连续整数序列的间隔(这个向量可以看作是一个因子,通过它可以将第二个向量分为几组)。

在这里,我为我的问题提出了一个假人。

数据,在第二个向量的一组(由第一个向量定义)中,整数单调递增。

my.data <- data.frame(
    V1=c(rep(1, 10), rep(2, 9), rep(3,11)), 
    V2=c(seq(2,5), seq(7,11), 13, seq(4, 9), seq(11,13), seq(1, 6), seq(101, 105))
)

我想要什么:

  • 输出区间的开始和结束
  • 这里,第一列是分组,第二列是开始整数,第三列是结束整数。

预期结果:

1, 2, 5 \n
1, 7, 11 \n
1, 13, 13 \n
2, 4, 9 \n
2, 11, 13 \n
3, 1, 6 \n
3, 101, 105 \n

【问题讨论】:

    标签: r aggregate


    【解决方案1】:

    这是一个使用聚合的简短答案......

    runs <- cumsum( c(0, diff(my.data$V2) > 1) )
    aggregate(V2 ~ runs + V1, my.data, range)[,-1]
    
    
      V1 V2.1 V2.2
    1  1    2    5
    2  1    7   11
    3  1   13   13
    4  2    4    9
    5  2   11   13
    6  3    1    6
    7  3  101  105
    

    【讨论】:

      【解决方案2】:

      不久前,我写了一个rle() 的变体,我将其命名为seqle(),因为它允许人们查找整数序列而不是重复。然后,你可以这样做:

      Rgames: seqle(my.data[my.data$V1==1,2]) #repeat for my.data$V1 equal to 2 and 3
      $lengths 
      [1] 4 5 1 
      
      $values 
      [1]  2  7 13 
      

      (例如)。将这些结果转换为您想要的表格形式需要一些麻烦,但只是想我会提到它。顺便说一句,这是seqle 的代码。如果你设置incr=0,你会得到基本的rle结果。

      function(x,incr=1){ 
      
          if(!is.numeric(x)) x <- as.numeric(x) 
          n <- length(x)  
          y <- x[-1L] != x[-n] + incr 
          i <- c(which(y|is.na(y)),n) 
          list( lengths = diff(c(0L,i)),  values = x[head(c(0L,i)+1L,-1L)]) 
      } 
      

      编辑:flodel 在How to check if a vector contains n consecutive numbers 提供了一个很好的升级。他指出,这个版本在处理双精度时存在常见的浮点错误问题,并提供了修复。

      【讨论】:

      • 我在this answer中使用了你的好功能。
      • (+1) 非常好用的功能!
      【解决方案3】:

      这是一个例子:

      library(plyr)
      
      ddply(my.data, .(V1), 
       function(x) data.frame(do.call("rbind", tapply(x$V2, cumsum(c(T, diff(x$V2)!=1)), 
         function(y) c(min(y), max(y))))))
      

      也许,太复杂了,但重要的是cumsum(c(T, diff(x$V2)!=1))

      > ddply(my.data, .(V1), 
      +  function(x) data.frame(do.call("rbind", tapply(x$V2, cumsum(c(T, diff(x$V2)!=1)), 
      +    function(y) c(min(y), max(y))))))
        V1  X1  X2
      1  1   2   5
      2  1   7  11
      3  1  13  13
      4  2   4   9
      5  2  11  13
      6  3   1   6
      7  3 101 105
      

      【讨论】:

      • 很高兴看到我们的思路相似。
      【解决方案4】:

      这是使用plyr 包中的ddply 的解决方案。基本思路是看diff(x)何时不为1,从而找到转换点。

      ddply(
        my.data,
        .(V1),
        summarise,
        lower =
        {
          cut_points <- which(diff(V2) != 1)
          V2[c(1, cut_points + 1)]
        },
        upper =
        {
          cut_points <- which(diff(V2) != 1)
          V2[c(cut_points, length(V2))]
        }
      )
      

      【讨论】:

        【解决方案5】:
        my.data$run <- ave(my.data$V2, my.data$V1, FUN=function(x) c(1, diff(x)))
        strstp <- by(my.data, list(my.data$V1), 
                         FUN=function(x) list(
                                   starts=c( head(x$V2,1), x$V2[x$run != 1]), 
                                   stops=c(x$V2[which(x$run != 1)-1], tail(x$V2, 1))))
        > strstp
        : 1
        $starts
        [1]  2  7 13
        
        $stops
        [1]  5 11 13
        
        ------------------------------------------------------------- 
        : 2
        $starts
        [1]  4 11
        
        $stops
        [1]  9 13
        
        ------------------------------------------------------------- 
        : 3
        $starts
        [1]   1 101
        
        $stops
        [1]   6 105
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-07-10
          • 1970-01-01
          • 2022-01-03
          • 2021-04-05
          • 1970-01-01
          • 1970-01-01
          • 2021-12-01
          • 1970-01-01
          相关资源
          最近更新 更多