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

如何在R数据框中按站点计算历史观测数与距上次观测时间步长?

解决方案

针对每个站点的每个时间步计算累计观测次数和距上次观测的步长,可以通过分组排序后结合累积求和、填充操作实现,以下是完整代码:

library(dplyr)
library(tidyr)

# 转换为长格式并处理计算
df_result <- all %>%
  # 宽格式转长格式(替代旧版gather,更灵活)
  pivot_longer(cols = -Site, names_to = "Date", values_to = "Observation") %>%
  # 将日期字符转为数值,方便排序和计算步长
  mutate(Date = as.numeric(Date)) %>%
  # 按站点分组,确保每个站点内时间顺序正确
  group_by(Site) %>%
  arrange(Date, .by_group = TRUE) %>%
  # 计算【当前时间步之前】的总观测次数:用lag取累积求和的上一步结果
  mutate(TotalObs = lag(cumsum(!is.na(Observation)), default = 0)) %>%
  # 计算距上次观测的时间步长
  mutate(
    # 标记有有效观测的时间点
    ObsDate = ifelse(!is.na(Observation), Date, NA),
    # 向下填充最近的有效观测时间点
    LastObsDate = fill(ObsDate, .direction = "down") %>% pull(ObsDate),
    # 步长 = (当前时间 - 上次观测时间)/0.5(每步对应0.5年即6个月)
    TimeSinceObs = ifelse(is.na(LastObsDate), NA, (Date - LastObsDate)/0.5)
  ) %>%
  # 移除中间辅助列
  select(-ObsDate, -LastObsDate) %>%
  ungroup()

关键步骤说明

  1. 长格式转换:用pivot_longer替代gather(tidyr官方推荐的新函数),将宽格式的时间列转为长格式的Date和Observation列。
  2. 日期数值化:把Date列的字符型时间(如"1992")转为数值,便于后续排序和计算时间差。
  3. 分组排序:按Site分组后按Date排序,确保每个站点的时间序列是有序的。
  4. 累计观测次数:
    • cumsum(!is.na(Observation))计算到当前时间步为止的总观测次数;
    • lag(..., default=0)取上一步的累积结果,得到当前时间步之前的总观测次数(首次时间步之前无观测,默认设为0)。
  5. 距上次观测步长:
    • 先标记有有效观测的时间点ObsDate;
    • 用fill向下填充最近的观测时间点到后续行;
    • 通过时间差除以单步间隔(0.5年)得到步长数,无历史观测时设为NA。

示例验证

以站点1的1993.5时间步为例:

  • 此前的1992、1992.5、1993三个时间步均有观测,因此TotalObs=3;
  • 上次观测时间是1993,与当前时间差为0.5年,除以单步间隔0.5得到TimeSinceObs=1,完全符合预期。

内容的提问来源于stack exchange,提问作者Christina Skinner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 17:50:42