为多站点多夜间数据创建15分钟时间块并填充物种存在/缺失数据
解决多站点夜间监测数据的15分钟时间块统计问题
看起来你需要的核心是生成完整的时间序列框架,把所有应该存在的15分钟时间块都包含进来,再和原始数据做连接,这样就能自动填充无记录块的0值了。下面是一步步的实现方案,用dplyr和lubridate包来处理日期时间会更高效:
第一步:准备环境与修正样本数据
首先加载必要的包,同时修正你样本数据里的小问题(Time向量少了一个元素,我补上了对应的值):
# 加载包 library(dplyr) library(lubridate) # 修正后的样本数据 Site <- c("1831", "1803", "1803", "1807", "1807", "1807", "1807") Date <- as.Date(c("05/05/2013", "06/05/2013", "06/05/2013", "06/05/2013", "06/05/2013", "08/05/2013", "08/05/2013"), format = "%d/%m/%Y") Time <- c("23:31:29", "22:22:57", "22:04:47", "22:58:45", "01:24:15", "22:04:47", "22:04:47") Present <- as.numeric(c("1", "1", "0", "1","0", "1", "1")) data <- data.frame(Site, Date, Time, Present)
第二步:处理日期时间,映射到正确的夜间日期
你的数据里可能存在跨天的记录(比如凌晨的记录属于前一天的夜间监测周期),所以首先要把每条记录映射到对应的夜间所属日期(即监测开始的日期,从当日19:45到次日06:30):
data_clean <- data %>% # 合并日期和时间为完整的datetime对象 mutate(datetime = dmy_hms(paste(Date, Time))) %>% # 确定每条记录所属的夜间日期:19:45及之后的记录属于当天夜间,之前的属于前一天夜间 mutate(NightDate = if_else( hour(datetime)*3600 + minute(datetime)*60 + second(datetime) >= 19*3600 + 45*60, date(datetime), date(datetime) - days(1) )) %>% # 把每条记录分配到对应的15分钟时间块(取时间块的起始时间) mutate(time_block = floor_date(datetime, unit = "15 minutes")) %>% # 过滤掉夜间监测范围外的记录(如果有的话) filter( time_block >= ymd_hms(paste(NightDate, "19:45:00")), time_block <= ymd_hms(paste(NightDate + days(1), "06:30:00")) )
第三步:生成完整的15分钟时间块框架
这是解决缺失值问题的关键——我们要为每个站点的每个夜间日期,生成从19:45到次日06:30的所有15分钟时间块:
# 获取所有唯一的站点-夜间日期组合 site_night_pairs <- data_clean %>% distinct(Site, NightDate) # 为每个组合生成完整的时间块序列 full_time_blocks <- site_night_pairs %>% rowwise() %>% mutate( time_block = list( seq( from = ymd_hms(paste(NightDate, "19:45:00")), to = ymd_hms(paste(NightDate + days(1), "06:30:00")), by = "15 mins" ) ) ) %>% unnest(time_block)
第四步:统计每个时间块的存在/缺失次数
现在把原始数据的统计结果和完整时间块框架做左连接,自动填充无记录块的0值:
final_stats <- full_time_blocks %>% # 左连接原始数据的统计结果 left_join( data_clean %>% group_by(Site, NightDate, time_block) %>% summarise( present_count = sum(Present == 1), # 存在次数 absent_count = sum(Present == 0), # 缺失次数(触发但未检测到) .groups = "drop" ), by = c("Site", "NightDate", "time_block") ) %>% # 把无记录的块的计数替换为0 mutate( present_count = replace_na(present_count, 0), absent_count = replace_na(absent_count, 0) )
结果说明
这样得到的final_stats就是你需要的数据集:
- 每个
Site+NightDate组合都包含了从19:45到次日06:30的所有15分钟时间块 - 有记录的块会统计
present_count(目标物种出现的次数)和absent_count(探测器触发但未检测到的次数) - 没有任何记录的块,这两个计数都会显示为0
比如你样本里的站点1831、NightDate=2013-05-05,会包含从2013-05-05 19:45到2013-05-06 06:30的所有43个时间块,其中只有23:30这个块有1次存在记录,其他块的计数都是0。
内容的提问来源于stack exchange,提问作者DFinch
相关产品推荐
相关产品推荐

