我从RFID读取器中获取了一组数据,该数据记录了个别鸟类何时访巢。但是,木板的错误意味着它们经常会停止扫描一天,因此我不知道这只鸟是否去过巢。数据集包含最近检测时间以及先前检测日期和时间的记录。当董事会在上次已知访问之前的任何一天关闭时,我想用“未知”更新此“前次访问”列。
我的最小数据集如下:
date <- seq.POSIXt(ISOdate(2018, 7, 6), ISOdate(2018,7,16), by = "day")
status <- c("ON","ON","OFF","ON","ON", "ON", "ON", "ON", "ON","ON", "ON")
firstdet <- c("2018-07-07 03:34:58 BST", NA, NA , NA ,
NA , "2018-07-12 01:30:37 BST","2018-07-13 03:15:55 BST", "2018-07-14 00:01:39 BST",
"2018-07-14 23:46:47 BST" ,"2018-07-15 23:28:16 BST" ,"2018-07-16 23:57:00 BST")
prevVisit <- c(NA, NA, NA, NA, NA ,"2018-07-07 03:34:58 BST", "2018-07-12 01:30:37 BST",
"2018-07-13 03:15:55 BST", "2018-07-14 00:01:39 BST",
"2018-07-14 23:46:47 BST" ,"2018-07-15 23:28:16 BST")
mydf <- data.frame(cbind(as.character(date), status, firstdet, prevVisit))
colnames(mydf)[1] <- "date"
看起来像这样:
date status firstdet prevVisit
1 2018-07-06 12:00:00 ON 2018-07-07 03:34:58 BST <NA>
2 2018-07-07 12:00:00 ON <NA> <NA>
3 2018-07-08 12:00:00 OFF <NA> <NA>
4 2018-07-09 12:00:00 ON <NA> <NA>
5 2018-07-10 12:00:00 ON <NA> <NA>
6 2018-07-11 12:00:00 ON 2018-07-12 01:30:37 BST 2018-07-07 03:34:58 BST
7 2018-07-12 12:00:00 ON 2018-07-13 03:15:55 BST 2018-07-12 01:30:37 BST
8 2018-07-13 12:00:00 ON 2018-07-14 00:01:39 BST 2018-07-13 03:15:55 BST
9 2018-07-14 12:00:00 ON 2018-07-14 23:46:47 BST 2018-07-14 00:01:39 BST
10 2018-07-15 12:00:00 ON 2018-07-15 23:28:16 BST 2018-07-14 23:46:47 BST
11 2018-07-16 12:00:00 ON 2018-07-16 23:57:00 BST 2018-07-15 23:28:16 BST
N.B。鸟类在晚上22:00至03:00之间探访,因此日期栏是指夜晚开始的日期;这就是为什么firstdet列日期不总是与日期匹配的原因。
只要当前检测到最后一个已知状态之间的任何行包含状态“ OFF”,我都希望“ prevVisit”列更新为“ unknown”(未知),因为我不确定最后一次访问该鸟的时间。例如:
date status firstdet prevVisit
1 2018-07-06 12:00:00 ON 2018-07-07 03:34:58 BST <NA>
2 2018-07-07 12:00:00 ON <NA> <NA>
3 2018-07-08 12:00:00 OFF <NA> <NA>
4 2018-07-09 12:00:00 ON <NA> <NA>
5 2018-07-10 12:00:00 ON <NA> <NA>
6 2018-07-11 12:00:00 ON 2018-07-12 01:30:37 BST UNKNOWN
7 2018-07-12 12:00:00 ON 2018-07-13 03:15:55 BST 2018-07-12 01:30:37 BST
8 2018-07-13 12:00:00 ON 2018-07-14 00:01:39 BST 2018-07-13 03:15:55 BST
9 2018-07-14 12:00:00 ON 2018-07-14 23:46:47 BST 2018-07-14 00:01:39 BST
10 2018-07-15 12:00:00 ON 2018-07-15 23:28:16 BST 2018-07-14 23:46:47 BST
11 2018-07-16 12:00:00 ON 2018-07-16 23:57:00 BST 2018-07-15 23:28:16 BST
我遇到了很多问题,这些问题询问如何根据前几行来更改行值,但是这些似乎都不以前几行的可变范围为条件,因此它们还没有解决我的问题。
我得到的最接近的是ifelse语句,希望该语句在状态列的前几行中搜索“ OFF”-但这不起作用:
mydf$prevVisit <- ifelse("OFF" %in% mydf$status[which(mydf$date > mydf$prevVisit & mydf$date < mydf$firstdet)], "unknown", mydf$prevVisit)
答案 0 :(得分:1)
我认为没有一种优雅的/可矢量化的方法可以解决此问题,ifelse
当然不会做您想要的事情。这是一个可能对您有用的快速技巧。
我稍微修改了您的数据以进行另一次测试(我没有在空白处错误地分配“未知”):
x <- read.table(stringsAsFactors=FALSE, header=TRUE, text="
date status firstdet prevVisit
2018-07-06_12:00:00 ON 2018-07-07_03:34:58_BST NA
2018-07-07_12:00:00 ON NA NA
2018-07-08_12:00:00 OFF NA NA
2018-07-09_12:00:00 ON NA NA
2018-07-10_12:00:00 ON NA NA
2018-07-11_12:00:00 ON 2018-07-12_01:30:37_BST 2018-07-07_03:34:58_BST
2018-07-12_12:00:00 ON 2018-07-13_03:15:55_BST 2018-07-12_01:30:37_BST
2018-07-13_12:00:00 ON 2018-07-14_00:01:39_BST 2018-07-13_03:15:55_BST
2018-07-14_12:00:00 ON NA 2018-07-14_00:01:39_BST
2018-07-15_12:00:00 ON 2018-07-15_23:28:16_BST 2018-07-14_00:01:39_BST
2018-07-16_12:00:00 ON 2018-07-16_23:57:00_BST 2018-07-15_23:28:16_BST")
x[] <- lapply(x, function(a) gsub("_", " ", a))
x$unknown <- c(FALSE, sapply(seq_len(nrow(x))[-1], function(i) {
prev <- tail(which(!is.na(x$firstdet[seq_len(i-1)])), n = 1)
!is.na(x$firstdet[i]) && (!length(prev) || any(x$status[prev:i] == "OFF"))
}))
x$prevVisit <- ifelse(is.na(x$firstdet) | x$unknown, NA, lag(zoo::na.locf(x$firstdet)))
x
# date status firstdet prevVisit unknown
# 1 2018-07-06 12:00:00 ON 2018-07-07 03:34:58 BST <NA> FALSE
# 2 2018-07-07 12:00:00 ON <NA> <NA> FALSE
# 3 2018-07-08 12:00:00 OFF <NA> <NA> FALSE
# 4 2018-07-09 12:00:00 ON <NA> <NA> FALSE
# 5 2018-07-10 12:00:00 ON <NA> <NA> FALSE
# 6 2018-07-11 12:00:00 ON 2018-07-12 01:30:37 BST <NA> TRUE
# 7 2018-07-12 12:00:00 ON 2018-07-13 03:15:55 BST 2018-07-12 01:30:37 BST FALSE
# 8 2018-07-13 12:00:00 ON 2018-07-14 00:01:39 BST 2018-07-13 03:15:55 BST FALSE
# 9 2018-07-14 12:00:00 ON <NA> <NA> FALSE
# 10 2018-07-15 12:00:00 ON 2018-07-15 23:28:16 BST 2018-07-14 00:01:39 BST FALSE
# 11 2018-07-16 12:00:00 ON 2018-07-16 23:57:00 BST 2018-07-15 23:28:16 BST FALSE
(修改后的数据显示,尽管第9行有空格,第10行仍显示第8行的firstdet
。)
我假设您打算一次制作这些真实的日期,所以我将其保留在单独的列中(因为"UNKNOWN"
列中不能有POSIXt
)。如果您真的想要在那儿,还可以做
x$prevVisit <- ifelse(x$unknown, "UNKNOWN", x$prevVisit)