如果您使用lubridate 包及其floor_date 函数,您可以向下舍入到最接近的15 分钟。这允许您将left_join 的数据添加到由grid.expand 获得的所有站点的所有时间的完整列表中。
您的数据不可重现,因为生成它的代码包含一些错误 - 我不得不稍微更改代码以将数据放入连贯的数据框中。以下应使数据可重现:
library(lubridate)
library(dplyr)
Site <- c("1831", "1803", "1803", "1807", "1807", "1807", "1807")
Date <- dmy(c("05/05/2013", "06/05/2013", "06/05/2013", "06/05/2013",
"06/05/2013", "08/05/2013", "08/05/2013"))
Time <- c("23:31:29", "22:22:57", "22:04:47", "22:58:45", "01:24:15",
"22:04:47", "03:45:02")
Present <- as.numeric(c("1", "1", "0", "1","0", "1", "1"))
data <- data.frame(Site, Date, Time, Present)
我做的第一件事是将日期和时间合并成统一的日期时间,以使左连接更容易,并将它们四舍五入到最接近的 15 分钟:
data$date_time <- floor_date(as.POSIXct(paste(data$Date, data$Time)),
"15 minutes")
接下来,我们通过从您的数据中获取每个日期并为每个日期添加从 19:45 到第二天早上 06:30 的 15 分钟序列来获取所有可能的时间:
all_times <- do.call(c, sapply(unique(data$Date),
function(x) x + minutes(15) * seq(75, 118, 1)))
现在为了方便左连接,我们可以从data 中删除我们不再需要的列:
data <- data[, c("Site", "date_time", "Present")]
接下来我们创建一个数据框,其中包含所有站点所有时间的列:
df <- expand.grid(date_time = all_times, Site = unique(data$Site))[2:1]
df$date_time <- as.POSIXct(df$date_time)
最后,我们将数据加入到这个新的数据框中,用 1 填充生成的 NA 值:
df <- left_join(df, data, by = c("Site", "date_time"))
df$Present[is.na(df$Present)] <- 0
我们生成的数据框有 396 行长,所以我在这里只显示前 20 行:
head(df, 20)
#> Site date_time Present
#> 1 1831 2013-05-05 19:45:00 0
#> 2 1831 2013-05-05 20:00:00 0
#> 3 1831 2013-05-05 20:15:00 0
#> 4 1831 2013-05-05 20:30:00 0
#> 5 1831 2013-05-05 20:45:00 0
#> 6 1831 2013-05-05 21:00:00 0
#> 7 1831 2013-05-05 21:15:00 0
#> 8 1831 2013-05-05 21:30:00 0
#> 9 1831 2013-05-05 21:45:00 0
#> 10 1831 2013-05-05 22:00:00 0
#> 11 1831 2013-05-05 22:15:00 0
#> 12 1831 2013-05-05 22:30:00 0
#> 13 1831 2013-05-05 22:45:00 0
#> 14 1831 2013-05-05 23:00:00 0
#> 15 1831 2013-05-05 23:15:00 0
#> 16 1831 2013-05-05 23:30:00 1
#> 17 1831 2013-05-05 23:45:00 0
#> 18 1831 2013-05-06 00:00:00 0
#> 19 1831 2013-05-06 00:15:00 0
#> 20 1831 2013-05-06 00:30:00 0
由reprex package (v0.3.0) 于 2020 年 7 月 30 日创建