我有一个包含许多变量的数据框(潜水),包括:
diveNum bottomTime
[,1] 2 FALSE
[,2] 2 FALSE
[,3] 2 TRUE
[,4] 2 TRUE
[,5] 2 FALSE
[,6] 2 TRUE
[,7] 2 FALSE
[,8] 3 FALSE
[,9] 3 TRUE
[,10] 3 FALSE
[,11] 3 TRUE
[,12] 3 TRUE
[,13] 3 FALSE
对于每个独特的diveNum,我想在bottomTime为TRUE的第一次和最后一次选择(& including)之间的所有行,给出:
diveNum bottomTime
[,3] 2 TRUE
[,4] 2 TRUE
[,5] 2 FALSE
[,6] 2 TRUE
[,9] 3 TRUE
[,10] 3 FALSE
[,11] 3 TRUE
[,12] 3 TRUE
ddply一直是我的朋友,因为类似的问题,我可以通过首先将数据子集化为仅包括bottomTime为“TRUE”然后运行ddply的情况来确定每个diveNum中的“TRUE”的第一个和最后一个记录:
dives <- dives[dives$bottomTime == "TRUE",]
bottomTime <- ddply(dives, .(diveNum), function(x) x[c(1, nrow(x)), ])
这给出了:
X diveNum bottomTime
[,1] 3 2 TRUE
[,2] 6 2 TRUE
[,3] 9 3 TRUE
[,4] 12 3 TRUE
我无法管理的是在每次潜水(存储在X中)中使用“TRUE”的第一个和最后一个记录的行号作为索引来对原始数据帧进行子集化。我一直在努力解决这个问题,我们将非常感谢任何帮助!
答案 0 :(得分:3)
以下是使用data.table
library(data.table)
setDT(dives)
dives[dives[, do.call(seq,as.list(range(.I[bottomTime]))),by=diveNum][['V1']]]
# or
dives[dives[,.I[cummax(bottomTime) &rev(cummax(rev(bottomTime)))],by=diveNum][['V1']]]
# or
dives[,.SD[cummax(bottomTime) &rev(cummax(rev(bottomTime)))],by=diveNum]
#or
dives[dives[(bottomTime),seq(.I[1],.I[.N]),by=diveNum][['V1']]]
使用plyr::ddply
ddply(dives, .(diveNum), function(x,ind) {
x[do.call(seq, as.list(range(which(x[[ind]])))),]
} ,ind='bottomTime')
或使用dplyr
dives %>% group_by(diveNum) %>%
filter(cumany(bottomTime) & rev(cumany(rev(bottomTime))))
答案 1 :(得分:3)
可能不是最佳方式,但在基数R中,您可以将split
与do.call(rbind, ...)
> do.call(rbind, lapply(split(dives, dives$diveNum), function(x){
w <- which(x$bottomTime)
x[ w[1]:tail(w, 1), ]
}))
# diveNum bottomTime
# 2.3 2 TRUE
# 2.4 2 TRUE
# 2.5 2 FALSE
# 2.6 2 TRUE
# 3.9 3 TRUE
# 3.10 3 FALSE
# 3.11 3 TRUE
# 3.12 3 TRUE
正如评论中所提到的,“更顺畅”的方法是使用by()
并避免两次调用lapply(split(...))
> do.call(rbind, by(dives, dives$diveNum, function(x) {
w <- which(x$bottomTime)
x[ w[1]:tail(w, 1), ]
}))
我只是想让事情比实际上更困难。