代码之家  ›  专栏  ›  技术社区  ›  monch1962

在数据帧中汇总分组记录

  •  2
  • monch1962  · 技术社区  · 16 年前

    我在R中有一个数据帧,看起来像这样:

    > TimeOffset, Source, Length 
    > 0         1           1500
    > 0.1       1           1000    
    > 0.2       1           50
    > 0.4       2           25
    > 0.6       2           3
    > 1.1       1           1500
    > 1.4       1           18
    > 1.6       2           2500
    > 1.9       2           18
    > 2.1       1           37
    > ...
    

    > TimeOffset, Source, Length
    > 0.2         1       2550
    > 0.6         2       28
    > 1.4         1       1518
    > 1.9         2       2518
    > ...
    

    试着把它译成英语,我想把具有相同“来源”的连续记录分组在一起,然后打印出每组的一条记录,显示该组中的最高时间偏移量、来源以及该组中的长度总和。

    时间偏移值将始终增加。

    提前感谢您提供的任何帮助

    3 回复  |  直到 8 年前
        1
  •  6
  •   Ian Fellows    16 年前

    首先你需要创建一个 id

    > dat <- data.frame(    TimeOffset = c(0,.1,.2,.4,.6,1.1,1.4,1.6,1.9,2.1),
    + Source=c(1,1,1,2,2,1,1,2,2,1),
    + Length=c(1500,1000,50,25,3,1500,18,2500,18,37))
    > dat
       TimeOffset Source Length
    1         0.0      1   1500
    2         0.1      1   1000
    3         0.2      1     50
    4         0.4      2     25
    5         0.6      2      3
    6         1.1      1   1500
    7         1.4      1     18
    8         1.6      2   2500
    9         1.9      2     18
    10        2.1      1     37
    > 
    > id <- cumsum(c(TRUE,diff(dat$Source)!=0))
    > id
     [1] 1 1 1 2 2 3 3 4 4 5
    > 
    > cbind(TimeOffset=tapply(dat$TimeOffset,id,max),
    + Source=tapply(dat$Source,id,max),
    + Length=tapply(dat$Length,id,sum))
      TimeOffset Source Length
    1        0.2      1   2550
    2        0.6      2     28
    3        1.4      1   1518
    4        1.9      2   2518
    5        2.1      1     37
    
        2
  •  2
  •   Yorgos    16 年前

    我刚看到,我喜欢伊恩的解决方案。我的太复杂了。。。

    df <- read.table(textConnection("
    TimeOffset Source Length 
     0         1           1500
     0.1       1           1000    
     0.2       1           50
     0.4       2           25
     0.6       2           3
     1.1       1           1500
     1.4       1           18
     1.6       2           2500
     1.9       2           18
     2.1       1           37
    "),header=T)
    
    
    ind <- cbind(rle(df$Source)[[1]],cumsum(rle(df$Source)[[1]]))
    ind2 <- apply(ind,1,function(x) c(x[2]-(x[1]-1),x[2]))
    ldply(apply(ind2,2,function(x) data.frame(df[x[2],1:2], Length=sum(df[x[1]:x[2],3]) ) ))
    
      TimeOffset Source Length
    1        0.2      1   2550
    2        0.6      2     28
    3        1.4      1   1518
    4        1.9      2   2518
    5        2.1      1     37
    
        3
  •  0
  •   doug    16 年前
    # 'dfx' refers to the 'input' data frame in OP's Question
    # use run-length encoding to get contiguous rows having the same Source value
    a = rle(dfx$Source)
    row_groups = a$lengths
    
    result = matrix(rep(0,3))   
    attr(result, "dim") = c(1,3)
    
    fnx = function(a_df){
      c1 = max(a_df[,1])
      c2 = a_df[1,2]
      c3 = sum(a_df[,3])
      cbind(c1, c2, c3)
    }
    
    
    for (itm in row_groups){
      px = dfx[1:itm,]
      dfx = dfx[-(1:dim(px)[1]),]
      result = rbind(result, fnx(px))
    }
    
    result = result[-1,]
    # returns:  
         c1  c2  c3
    [1,] 0.2  1 2550
    [2,] 0.6  2   28
    [3,] 1.4  1 1518
    [4,] 1.9  2 2518
    [5,] 2.1  1   37