如何选择所有

时间:2014-06-20 02:17:25

标签: r dataframe subset plyr

我有一个包含许多变量的数据框(潜水),包括:

     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”的第一个和最后一个记录的行号作为索引来对原始数据帧进行子集化。我一直在努力解决这个问题,我们将非常感谢任何帮助!

2 个答案:

答案 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中,您可以将splitdo.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), ]
      }))

我只是想让事情比实际上更困难。