我有一组来自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列的日期并不总是与日期匹配的原因
我希望"prevVisit"列更新为"unknown",只要当前检测和最后一个已知检测之间的任何一行包含状态"OFF",因为我不确定这只鸟最后一次访问是什么时候。例如:
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)
我认为没有一种优雅/可向量化的方法来实现这一点,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
(修改后的数据显示,行10显示了行8的firstdet
,尽管行9中存在间隙。(
我假设您打算在某一点上确定这些实际日期,所以我将其保存在一个单独的列中(因为"UNKNOWN"
不能包含在POSIXt
列中(。如果你真的想把它放在那里,你也可以做
x$prevVisit <- ifelse(x$unknown, "UNKNOWN", x$prevVisit)