2011-03-07 91 views
4

我喜歡選擇數據框中每個組的第一個(2,3,0,4)行。按行數選擇第一個第n行

> f<-data.frame(group=c(1,1,1,2,2,3,4),y=c(1:7)) 
> 
> group y 
>  1 1 
>  1 2 
>  1 3 
>  2 4 
>  2 5 
>  3 6 
>  4 7 

,將獲得的數據幀如下

group y 
1 1 
1 2 
2 4 
2 5 
4 7 

我試圖使用byhead但頭不採取的載體。

謝謝你的幫助。

回答

1

具有索引的函數的版本。

fun1 <- function(){ 
    idx <- c(0,which(diff(f$group)!=0))+1 
    idx2 <- unlist(lapply(1:length(nf),function(x) seq.int(from=idx[x],length.out=nf[x])),use.names=F) 
    f1 <- f[idx2,] 
    return(f1) 
} 

fun2 <- function(){ 
    ddply(f,.(group),function(x) head(x,nf[x[1,1]])) 
} 

測試數據(按大小問題筆者建議)

f<-data.frame(group=sample(1:1000,50000,T),y=c(1:50000)) 
f <- f[order(f$group),] 
nf <- rpois(length(unique(f$group)),3) 

system.time(FUN1()) system.time(FUN2())

在我的系統〜60時間更快樂趣1。

+0

我用我的數據集測試你的代碼,確實非常快。對於ddply,我得到以下錯誤消息:錯誤if(n <0L)max(nrow(x)+ n,0L)else min(n,nrow(x)): 缺少值,其中TRUE/FALSE需要' – Tony 2011-03-08 01:20:38

+0

可能你在組變量中缺少值。您可以重新編碼丟失某些值或使用na.omit(f)。 – 2011-03-08 07:52:06

2

使用plyr

library(plyr) 
rows <- c(2,3,0,4) 
ddply(f,.(group),function(x)head(x,rows[x[1,1]])) 
     group y 
    1  1 1 
    2  1 2 
    3  2 4 
    4  2 5 
    5  4 7 

編輯:

誤解所以更新的答案

5

與傳統的lapply問題:

k <- c(2,3,0,4) 
fs <- split(f, f$group) 
do.call(rbind,lapply(seq_along(k), function(i) head(fs[[i]], k[i]))) 

結果是:

group y 
1  1 1 
2  1 2 
4  2 4 
5  2 5 
7  4 7 
+0

我幾乎提交了幾乎相同的代碼...再次。我們相似地思考_very_。 – 2011-03-07 18:13:31

+0

@Joshua:謝謝你的誇獎。我很欣賞你在這裏的許多有用的答案。順便說一句,我看到我今天早些時候比你更快,只是因爲你先編輯了問題 - 感謝花時間讓問題更好。 – Aaron 2011-03-07 18:16:46

+0

乾淨利落的做法。我在該組中有大約5萬個類別的大數據框。任何想法這是多快。乾杯 – Tony 2011-03-07 18:24:10