我有一个数据框,其中包含列名为FirmID和DEF的数据行。列DEF仅包含零。 FirmID列包含公司ID。我想对给定的FirmID进行最后2次观察。 DEF列仅为零。
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
... . . .
... . . .
那么如何获得给定FirmID的最后两行
1004 . . 0
1004 . . 0
1021 . . 0
1021 . . 0
1035 . . 0
1035 . . 0
答案 0 :(得分: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]
答案 1 :(得分:4)
为您提供数据称为DF
:
lasttwo <- do.call(rbind,by(DF,DF$FirmID,tail,2))
答案 2 :(得分:3)
执行此操作的base-R方法是手动执行split-apply-combine舞蹈。使用您的数据:
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)
我们
FirmID
:split(dat, dat$FirmID)
。这将返回我们lapply
结束,应用tail
函数最多返回最后两行,结果是一个列表,其组件是tail
的结果,然后我们< / LI>
do.call
和rbind
整个电话可以串成一行:
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