加速data.frame重新排列

时间:2015-11-05 19:57:44

标签: r dataframe

我有一个带坐标的数据框("开始","结束")和标签(" group"):

a <- data.frame(start=1:4, end=3:6, group=c("A","B","C","D"))
a
  start end group
1     1   3     A
2     2   4     B
3     3   5     C
4     4   6     D

我想创建一个新的数据框,其中标签被分配给坐标范围内序列的每个元素:

   V1 V2
1   1  A
2   2  A
3   3  A
4   2  B
5   3  B
6   4  B
7   3  C
8   4  C
9   5  C
10  4  D
11  5  D
12  6  D

以下代码可以正常工作,但是范围很宽:

df<-data.frame()
for(i in 1:dim(a)[1]){
    s<-seq(a[i,1],a[i,2])
    df<-rbind(df,data.frame(s,rep(a[i,3],length(s))))
}
colnames(df)<-c("V1","V2")

如何加快速度?

2 个答案:

答案 0 :(得分:4)

您可以尝试 data.table

library(data.table)
setDT(a)[, start:end, by = group]

给出了

    group V1
 1:     A  1
 2:     A  2
 3:     A  3
 4:     B  2
 5:     B  3
 6:     B  4
 7:     C  3
 8:     C  4
 9:     C  5
10:     D  4
11:     D  5
12:     D  6

显然,只有当你每组有一行时才会这样做,这似乎你在这里。

答案 1 :(得分:1)

如果您想在基础R中使用非常快速的解决方案,可以分两步手动创建data.frame

  1. 使用mapply创建范围从“开始”到“结束”的list
  2. 使用rep + lengths将“groups”列重复为预期的行数。
  3. 此处共享的基本R方法不依赖于每组只有一行。

    尝试:

    temp <- mapply(":", a[["start"]], a[["end"]], SIMPLIFY = FALSE)
    data.frame(group = rep(a[["group"]], lengths(temp)),
               values = unlist(temp, use.names = FALSE))
    

    如果你做了很多,只需把它放在一个函数中:

    myFun <- function(indf) {
      temp <- mapply(":", indf[["start"]], indf[["end"]], SIMPLIFY = FALSE)
      data.frame(group = rep(indf[["group"]], lengths(temp)),
                 values = unlist(temp, use.names = FALSE))
    }
    

    然后,如果您想要一些样本数据,可以使用以下作为样本数据:

    set.seed(1)
    a <- data.frame(start=1:4, end=sample(5:10, 4, TRUE), group=c("A","B","C","D"))
    x <- do.call(rbind, replicate(1000, a, FALSE))
    y <- do.call(rbind, replicate(100, x, FALSE))
    

    请注意,随着“group”中不同唯一值的数量增加,这似乎会变慢。

    (换句话说,“data.table”方法通常是最有意义的。我只是分享一个可能的基本R替代方案,它应该比现有方法快得多。)