2013-03-19 91 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]