条件过滤data.frame与前面和拖尾NA观察

时间:2015-06-23 20:31:56

标签: r dplyr

我有一个由观察和模型预测数据组成的data.frame。最小的示例数据集可能如下所示:

myData <- data.frame(tree=c(rep("A", 20)), doy=c(seq(75, 94)), count=c(NA,NA,NA,NA,0,NA,NA,NA,NA,1,NA,NA,NA,NA,2,NA,NA,NA,NA,NA), pred=c(0,0,0,0,1,1,1,2,2,2,2,3,3,3,3,6,9,12,20,44))

计数列表示何时进行观察并在一整天内对预测进行建模,实际上将数据内插到日期级别(每5天)。

我想有条件地过滤此数据集,以便最终将预测截断到与观察值相同的范围,实际上保持计数开始和结束之间的所有预测(即删除前导和尾随行/值的时间)它们对应于计数列中的NA)。对于这个例子,理想的结果是:

   tree doy count pred
5     A  79     0    1
6     A  80    NA    1
7     A  81    NA    1
8     A  82    NA    2
9     A  83    NA    2
10    A  84     1    2
11    A  85    NA    2
12    A  86    NA    3
13    A  87    NA    3
14    A  88    NA    3
15    A  89     2    3

我尝试通过将filterfirstlast相结合来解决此问题,考虑使用条件mutate来创建确定是否存在的列在之前的doy中观察(可能使用lag)并用1或0填充并使用该输出进行过滤,甚至创建第二个data.frame,其中包含可以连接到此数据的正确doy范围

在我对StackOverflow的搜索中,我遇到了以下似乎很接近但仍然不是我需要的问题:

Select first observed data and utilize mutate

Conditional filtering based on the level of a factor R

我的实际数据集在多年中有多棵树(每棵树/年具有不同的观察时段,具体取决于站点的高度等)。我目前正在我的代码中实现dplyr包,因此在该框架内的答案会很棒但是对任何解决方案都很满意。

2 个答案:

答案 0 :(得分:1)

尝试

  indx <- which(!is.na(myData$count))
  myData[seq(indx[1], indx[length(indx)]),]
  #    tree doy count pred
  #5     A  79     0    1
  #6     A  80    NA    1
  #7     A  81    NA    1
  #8     A  82    NA    2
  #9     A  83    NA    2
  #10    A  84     1    2
  #11    A  85    NA    2
  #12    A  86    NA    3
  #13    A  87    NA    3
  #14    A  88    NA    3
  #15    A  89     2    3

如果这是基于群组

 ind <- with(myData, ave(!is.na(count), tree,
           FUN=function(x) cumsum(x)>0 & rev(cumsum(rev(x))>0)))
  myData[ind,]
 #   tree doy count pred
 #5     A  79     0    1
 #6     A  80    NA    1
 #7     A  81    NA    1
 #8     A  82    NA    2
 #9     A  83    NA    2
 #10    A  84     1    2
 #11    A  85    NA    2
 #12    A  86    NA    3
 #13    A  87    NA    3
 #14    A  88    NA    3
 #15    A  89     2    3

或使用na.trim

中的zoo
 library(zoo)
 do.call(rbind,by(myData, myData$tree, FUN=na.trim))

或使用data.table

 library(data.table)
 setDT(myData)[,.SD[do.call(`:`,as.list(range(.I[!is.na(count)])))] , tree]
 #   tree doy count pred
 #1:    A  79     0    1
 #2:    A  80    NA    1
 #3:    A  81    NA    1
 #4:    A  82    NA    2
 #5:    A  83    NA    2
 #6:    A  84     1    2
 #7:    A  85    NA    2
 #8:    A  86    NA    3
 #9:    A  87    NA    3
 #10:   A  88    NA    3
 #11:   A  89     2    3

答案 1 :(得分:1)

我认为您只是希望将行限制在第一个和最后一个非NA计数值之间:

myData[seq(min(which(!is.na(myData$count))), max(which(!is.na(myData$count)))),]
#    tree doy count pred
# 5     A  79     0    1
# 6     A  80    NA    1
# 7     A  81    NA    1
# 8     A  82    NA    2
# 9     A  83    NA    2
# 10    A  84     1    2
# 11    A  85    NA    2
# 12    A  86    NA    3
# 13    A  87    NA    3
# 14    A  88    NA    3
# 15    A  89     2    3

dplyr语法中,按tree变量进行分组:

library(dplyr)
myData %>%
  group_by(tree) %>%
  filter(seq_along(count) >= min(which(!is.na(count))) &
         seq_along(count) <= max(which(!is.na(count))))
# Source: local data frame [11 x 4]
# Groups: tree
# 
#    tree doy count pred
# 1     A  79     0    1
# 2     A  80    NA    1
# 3     A  81    NA    1
# 4     A  82    NA    2
# 5     A  83    NA    2
# 6     A  84     1    2
# 7     A  85    NA    2
# 8     A  86    NA    3
# 9     A  87    NA    3
# 10    A  88    NA    3
# 11    A  89     2    3