You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为多站点多夜间数据创建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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 16:22:57