data.frame 的条件过滤,前面和后面的 NA 观察
Conditional filtering of data.frame with preceeding and tailing NA observations
我有一个 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 天开始)。
我想有条件地过滤这个数据集,以便我最终将预测截断到与观察相同的范围内,实际上在计数开始和结束之间保持所有预测(即删除前面和后面 rows/values pred 当它们对应于计数列中的 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
我试图通过将filter
与first
和last
组合来解决这个问题,考虑使用条件mutate
创建一个列来确定是否存在是对前一个 doy 的观察(可能使用 lag
)并用 1 或 0 填充并使用该输出然后过滤,或者甚至创建第二个 data.frame 包含可以是的适当的 doy 范围加入此数据。
在我对 Whosebug 的搜索中,我遇到了以下看起来很接近的问题,但并不是我所需要的:
Conditional filtering based on the level of a factor R
我的实际数据集要大得多,多年来有多棵树(每棵 tree/year 都有不同的观察期,具体取决于地点的海拔等)。我目前正在我的代码中实施 dplyr
包,因此该框架内的答案会很好,但对任何解决方案都会感到满意。
尝试
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
我认为您只是希望将行限制在第一个和最后一个非 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
我有一个 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 天开始)。
我想有条件地过滤这个数据集,以便我最终将预测截断到与观察相同的范围内,实际上在计数开始和结束之间保持所有预测(即删除前面和后面 rows/values pred 当它们对应于计数列中的 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
我试图通过将filter
与first
和last
组合来解决这个问题,考虑使用条件mutate
创建一个列来确定是否存在是对前一个 doy 的观察(可能使用 lag
)并用 1 或 0 填充并使用该输出然后过滤,或者甚至创建第二个 data.frame 包含可以是的适当的 doy 范围加入此数据。
在我对 Whosebug 的搜索中,我遇到了以下看起来很接近的问题,但并不是我所需要的:
Conditional filtering based on the level of a factor R
我的实际数据集要大得多,多年来有多棵树(每棵 tree/year 都有不同的观察期,具体取决于地点的海拔等)。我目前正在我的代码中实施 dplyr
包,因此该框架内的答案会很好,但对任何解决方案都会感到满意。
尝试
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
我认为您只是希望将行限制在第一个和最后一个非 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