【问题标题】:Combining rows in a data.frame合并 data.frame 中的行
【发布时间】:2014-08-12 08:32:54
【问题描述】:

我有一个data.frame,看起来像这个例子data.frame

df = data.frame(id = c("a","b","c","d","e","f","g"), start = c(10,20,30,40,50,60,70), end = c(15,25,35,45,55,65,75), flag = c(0,1,1,0,1,0,1))
> df
  id start end flag
1  a    10  15    0
2  b    20  25    1
3  c    30  35    1
4  d    40  45    0
5  e    50  55    1
6  f    60  65    0
7  g    70  75    1

它按df$startdf$end 的升序排列。 我正在寻找一个函数,它将所有行与df$flag == 1 合并,这些行不会被df$flag == 0 的行干预。合并的行应该将它们的df$id 与逗号分隔符连接起来,它们的df$start 应该是带有min df$start 的行,它们的df$end 应该是带有max @987654334 的行@。最后,df$flag 对他们来说应该是 1。

所以对于这个例子,返回 data.frame 应该是:

res.df = data.frame(id = c("a","b,c","d","e","f","g"), start = c(10,20,40,50,60,70), end = c(15,35,45,55,65,75), flag = c(0,1,0,1,0,1))
> res.df
   id start end flag
1   a    10  15    0
2 b,c    20  35    1
3   d    40  45    0
4   e    50  55    1
5   f    60  65    0
6   g    70  75    1

【问题讨论】:

  • 您能否澄清end 的值?根据您的解释,听起来应该是 35,但您的 res.df 显示为 25。
  • 很抱歉。现在已经修好了。
  • 还有一个问题:合并的行是否会超过两行?

标签: r dataframe collapse


【解决方案1】:

aggregate 很难做到这一点,因为相同的函数会依次应用于每一列。多次调用aggregate 可以分块完成,然后合并。但是,data.table 允许在同一个调用中使用不同的聚合函数:

library(data.table)
d <- data.table(df)

d[,list(id=paste(id, collapse=','), start=min(start), end=max(end)), 
  by=list(flag, cumsum(flag==0))
]
   flag cumsum  id start end
1:    0      1   a    10  15
2:    1      1 b,c    20  35
3:    0      2   d    40  45
4:    1      2   e    50  55
5:    0      3   f    60  65
6:    1      3   g    70  75

您最终会得到一个新列,如果需要,可以将其删除。 cumsum(flag==0) 上的条件可防止将任何带有 flag==0 的行合并到聚合中,并在结果中保持非连续的 flag==1 值分开。

【讨论】:

    【解决方案2】:

    这是base 中使用aggregatemerge 的解决方案:

    merge(merge(aggregate(start ~ flag + cumsum(flag==0), data=df, FUN=min), 
               aggregate(end ~ flag + cumsum(flag==0), data=df, FUN=max)
          ), 
         aggregate(id ~ flag + cumsum(flag==0), data=df, FUN=paste, sep=',')
    )
      flag cumsum(flag == 0) start end   id
    1    0                 1    10  15    a
    2    0                 2    40  45    d
    3    0                 3    60  65    f
    4    1                 1    20  35 b, c
    5    1                 2    50  55    e
    6    1                 3    70  75    g
    

    如果您使用Reduce 和数据框列表进行合并,代码的可读性会更高:

    Reduce(merge, list(aggregate(start ~ flag + cumsum(flag==0), data=df, FUN=min), 
                       aggregate(end   ~ flag + cumsum(flag==0), data=df, FUN=max),
                       aggregate(id    ~ flag + cumsum(flag==0), data=df, FUN=paste, sep=',')
                  )
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-22
      • 2013-12-04
      • 2017-03-14
      • 1970-01-01
      • 2013-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多