2015-11-05 63 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選擇,它應該比現有方法快得多)。