2013-03-19 89 views
2

我有一個數據幀,其中包含列名爲FirmID和DEF的數據行。列DEF只包含零。 FirmID列包含公司ID。我想對給定的FirmID進行最後2次觀察。 DEF列只有零。獲取每組中的最後2行

FirmID LTQ DLCQ DEF 
1004 0.45 0.21 0 
1004 0.32 0.43 0 
1004 0.36 0.47 0 
1004 0.25 0.67 0 
1004 0.56 0.34 0 
1021 0.12 0.39 0 
1021 0.16 0.31 0 
1021 0.24 0.76 0 
1021 0.37 0.56 0 
1035 0.89 0.78 0 
...  . . . 
...  . . . 

那麼如何獲取只有最後2行對於給定FirmID

1004 . . 0 
1004 . . 0 
1021 . . 0 
1021 . . 0 
1035 . . 0 
1035 . . 0 
+1

因爲這些值都是相同的, *爲什麼它是頂部還是底部2 *?你可以採取'唯一'你的data.frame,然後'rbind'它自己一次... – Arun 2013-03-19 17:33:44

+0

+1 @Arun。提供一個現實的例子,或者你會得到一個解決方案,可能不會滿足你的*實際需要。或者,如果這個例子*是現實的,那麼Arun就有你的解決方案。 – ndoogan 2013-03-19 17:42:16

+0

謝謝阿倫,好點。我當然有幾行,實際上這是我最後兩行所需的數據。 – Maximilian 2013-03-19 17:43:13

回答

4

Suposing你的數據被稱爲DF

lasttwo <- do.call(rbind,by(DF,DF$FirmID,tail,2)) 
+0

感謝您的快速和正確的答案! – Maximilian 2013-03-19 18:12:28

3

的基-R的方式做,這是手動做分裂應用組合舞蹈。使用您的數據:

dat <- read.table(text = "FirmID LTQ DLCQ DEF 
1004 0.45 0.21 0 
1004 0.32 0.43 0 
1004 0.36 0.47 0 
1004 0.25 0.67 0 
1004 0.56 0.34 0 
1021 0.12 0.39 0 
1021 0.16 0.31 0 
1021 0.24 0.76 0 
1021 0.37 0.56 0 
1035 0.89 0.78 0", header = TRUE) 

我們

  1. 各執FirmID數據:split(dat, dat$FirmID)。這將返回一個列表,我們
  2. lapply結束,應用tail功能最多的最後兩行返回,這樣做的結果是,其成分是從tail結果的列表中,我們則
  3. 合併回成數據幀使用do.callrbind

整個呼叫可以一起串成一條線:

do.call("rbind", lapply(split(dat, dat$FirmID), tail, 2)) 

這給:

> (out <- do.call("rbind", lapply(split(dat, dat$FirmID), tail, 2))) 
     FirmID LTQ DLCQ DEF 
1004.4 1004 0.25 0.67 0 
1004.5 1004 0.56 0.34 0 
1021.8 1021 0.24 0.76 0 
1021.9 1021 0.37 0.56 0 
1035  1035 0.89 0.78 0 

如果你不喜歡那些討厭的行名字,只是將其刪除:

> rownames(out) <- NULL 
> out 
    FirmID LTQ DLCQ DEF 
1 1004 0.25 0.67 0 
2 1004 0.56 0.34 0 
3 1021 0.24 0.76 0 
4 1021 0.37 0.56 0 
5 1035 0.89 0.78 0 
+0

經過更新以匹配OP的新數據示例。 – 2013-03-19 17:51:21

+0

謝謝你Gavin。當然你的答案更好更正確,但是我已經給予Rcoster接受,因爲他在大約2分鐘前正確回答了。非常感謝! – Maximilian 2013-03-19 18:14:45

7

您可以使用「data.table」包如下(假設你開始與一個名爲「是myDF」)data.frame

> library(data.table) 
> DT <- data.table(mydf, key="FirmID") 
> DT[, tail(.SD, 2), by = key(DT)] 
    FirmID LTQ DLCQ DEF 
1: 1004 0.25 0.67 0 
2: 1004 0.56 0.34 0 
3: 1021 0.24 0.76 0 
4: 1021 0.37 0.56 0 
5: 1035 0.89 0.78 0 

顯然,「2」改爲你真的想(有一個在你的問題的標題和它的文本),一個矛盾的行數。


另一種選擇是在以類似的方式使用plyr

> library(plyr) 
> ddply(mydf, .(FirmID), tail, 2) 
    FirmID LTQ DLCQ DEF 
1 1004 0.25 0.67 0 
2 1004 0.56 0.34 0 
3 1021 0.24 0.76 0 
4 1021 0.37 0.56 0 
5 1035 0.89 0.78 0 

而且,一個不尋常的替代使用基R:

temp <- within(mydf, { 
    ID <- ave(FirmID, FirmID, FUN = function(x) rev(seq_along(x))) 
}) 

temp[temp$ID %in% c(1, 2), 1:4]