我在其他地方找不到这个答案,如果真的很抱歉,请指出正确的方向
我想测试一个大型数据集(因此没有循环),对于所有匹配一个变量的行(例如ID),然后测试第二个变量(例如Time)是否在2小时内。我想通过结合ID和时间来制作一个URN。
如果时间在2小时以内(小于或等于),我想使用与原始第一行相同的ID。
对于时差大于2小时的所有行,我想从此点开始创建新的URN。
使用数据可能更有意义:
ID Time URN URN_whichIwanttomake Index
hawk 09:05 hawk_09 hawk_09 1
hawk 09:10 hawk_09 hawk_09 2
hawk 10:00 hawk_10 hawk_09 3
hawk 11:00 hawk_11 hawk_09 4
hawk 15:00 hawk_15 hawk_15 5
hawk 16:00 hawk_16 hawk_15 6
eagle 12:00 eagle_12 eagle_12 7
eagle 12:20 eagle_12 eagle_12 8
eagle 12:45 eagle_12 eagle_12 9
eagle 13:50 eagle_13 eagle_12 10
eagle 14:00 eagle_14 eagle_12 11
eagle 14:30 eagle_14 eagle_14 12
eagle 15:15 eagle_15 eagle_14 13
我尝试在if语句中将向量与逻辑语句一起使用,我可以使我的逻辑正常工作并返回TRUE / FALSE的正确向量,但是我不能使用它来覆盖URN
到目前为止,我的代码:
IndexShiftedBy1 <- dt$Index + 1 # ie a vector which starts at 2 and goes up to 14
if ((dt$ID[dt$Index] == dt$ID[IndexShiftedBy1]) # ie if the two IDs are the same
& (dt$URN[dt$Index] != dt$URN[IndexShiftedBy1])) { # URN2 (ie time dependent) is NOT the same
dt$URN[IndexShiftedBy1] <- dt$URN[Index] } # overwrite lower row with upper row's value
现在,首先这是行不通的,其次,如果这样做了,那么我将不得不多次运行它,因为它将问题连续下移了!
非常感谢您提供的任何帮助,我显然缺少有用的功能/需要自己编写一个功能,但这超出了我的知识水平
这是一个整洁的解决方案。关键组成部分是zoo::na.locf
(不是tidyverse),它NA
用先前的非NA
值填充值。
library(dplyr)
# library(zoo)
dat %>%
group_by(ID) %>%
mutate(
URN_new = if_else(c(TRUE, `units<-`(diff(Time), "hours") > 2), URN_original, NA_character_),
URN_new = zoo::na.locf(URN_new)
) %>%
ungroup()
# # A tibble: 13 x 5
# ID Time URN_original URN_whichIwanttomake URN_new
# <chr> <dttm> <chr> <chr> <chr>
# 1 hawk 2018-10-26 09:05:00 hawk_09 hawk_09 hawk_09
# 2 hawk 2018-10-26 09:10:00 hawk_09 hawk_09 hawk_09
# 3 hawk 2018-10-26 10:00:00 hawk_10 hawk_09 hawk_09
# 4 hawk 2018-10-26 11:00:00 hawk_11 hawk_09 hawk_09
# 5 hawk 2018-10-26 15:00:00 hawk_15 hawk_15 hawk_15
# 6 hawk 2018-10-26 16:00:00 hawk_16 hawk_15 hawk_15
# 7 eagle 2018-10-26 12:00:00 eagle_12 eagle_12 eagle_12
# 8 eagle 2018-10-26 12:20:00 eagle_12 eagle_12 eagle_12
# 9 eagle 2018-10-26 12:45:00 eagle_12 eagle_12 eagle_12
# 10 eagle 2018-10-26 13:50:00 eagle_13 eagle_12 eagle_12
# 11 eagle 2018-10-26 14:00:00 eagle_14 eagle_12 eagle_12
# 12 eagle 2018-10-26 14:30:00 eagle_14 eagle_14 eagle_12
# 13 eagle 2018-10-26 15:15:00 eagle_15 eagle_14 eagle_12
data.table
替代方案:
library(data.table)
datdt <- as.data.table(dat)
datdt[,
URN_newdt := zoo::na.locf(
ifelse(c(TRUE, `units<-`(diff(Time), "hours") > 2), URN_original, NA_character_)
),
by = "ID"]
基数R:
ave(dat, dat$ID, FUN = function(d) {
d$URN_newave <- zoo::na.locf(
ifelse(c(TRUE, `units<-`(diff(d$Time), "hours") > 2), d$URN_original, NA_character_)
)
d
})
简要说明:zoo::na.locf
用NA
最近的非NA
值填充:
zoo::na.locf(c("hawk_09", NA, NA, NA, "hawk_15", NA))
# [1] "hawk_09" "hawk_09" "hawk_09" "hawk_09" "hawk_15" "hawk_15"
知道这一点,下一步就是弄清楚NA
当时间差小于两个小时时如何分配给新的URN。diff(dat$Time)
是足够直接的,尽管因为它可以在不发出警告的情况下返回不同的单位,所以我们需要将其封装起来units<-(..., "hours")
以确保获得所需的东西。
下一步,diff
返回向量长度减去1,因此我们需要确定是否需要添加前缀或附加元素,并且该附加值应为TRUE
还是FALSE
。在这种情况下,我们总是希望组中的第一个成为原始组,因此前置TRUE
是最有意义的。
数据:
dat <- read.table(header=TRUE, stringsAsFactors=FALSE, text="
ID Time URN_original URN_whichIwanttomake
hawk 09:05 hawk_09 hawk_09
hawk 09:10 hawk_09 hawk_09
hawk 10:00 hawk_10 hawk_09
hawk 11:00 hawk_11 hawk_09
hawk 15:00 hawk_15 hawk_15
hawk 16:00 hawk_16 hawk_15
eagle 12:00 eagle_12 eagle_12
eagle 12:20 eagle_12 eagle_12
eagle 12:45 eagle_12 eagle_12
eagle 13:50 eagle_13 eagle_12
eagle 14:00 eagle_14 eagle_12
eagle 14:30 eagle_14 eagle_14
eagle 15:15 eagle_15 eagle_14")
dat$Time <- as.POSIXct(paste(Sys.Date(), dat$Time))
POSIXt
为了方便起见,我使用“今天” 。我建议您使用类似的东西POSIXt
,但要由您决定时间的差异。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句