2015-11-05 67 views
3

我有一个坐标(“开始”,“结束”)和标签(“本集团”)的数据帧:加快data.frame重排

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") 

我该如何加快速度?

回答

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

如果你想在基础R非常快的解决方案,您可以手动创建两个data.frame步骤:

  1. 使用mapply来创建范围从list“开始”到“结束”。
  2. 使用rep + lengths将“组”列重复为期望的行数。

此处共享的基本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)) 

请注意,这似乎减慢了不同的唯一v “群体”中的线索增加。 (换句话说,“data.table”方法通常是最有意义的,我只是分享一个可能的基本R选择,它应该比现有方法快得多)。