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

基于R语言处理月度与季度混合面板数据:按ID分组实现当期与上期值的变动方向对比

解决分组后多频率面板数据的变动方向判断问题

这个场景的核心难点是不同id的数据频率不一致:M01、M02是月度连续数据,而S01是季度数据(只有部分月份有实际值),需要让每个有实际值的行,对应上一个有实际值的行的实际值来对比,而不是固定滞后1期。下面是完整的解决方案:

1. 加载依赖包并处理日期格式

首先确保你安装了dplyr和lubridate包,然后把原数据中的date因子转换成标准日期格式,保证时间顺序绝对正确:

library(dplyr)
library(lubridate)

# 你的原始数据
df <- structure(list(id = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("M01", "M02", "S01"), class = "factor"), date = structure(c(2L, 3L, 4L, 5L, 6L, 7L, 8L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L), .Label = c("2020-12", "2021-01", "2021-02", "2021-03", "2021-04", "2021-05", "2021-06", "2021-07"), class = "factor"), actual = c(3.4, 5.4, 7.4, 7.4, 7.5, 8, 8.9, 10.8, 10.1, 8.2, 10.1, 9.4, 10.1, 9.4, -0.3, NA, NA, 8.6, NA, NA, 8.3, NA), pred = c(3.288889774, 5.819407687, 6.705608369, 6.054457292, 5.582409131, 7.01052472, 9.742902434, 10.98571396, 6.522003651, 9.688977242, 10.39801463, 9.398991615, 9.764616936, 9.855033457, 0.493311422, 8.403722942, 8.174854517, 8.573117852, 8.403065801, 8.684289455, 8.719079247, 8.259439468)), class = "data.frame", row.names = c(NA, -22L))

# 转换日期格式
df <- df %>% mutate(date = ym(date))

2. 创建对比周期分组,匹配对应上期实际值

这里的关键是给每个id下的有效实际值行(actual非NA)创建递增分组,让每个分组内的所有行共享上一个有效实际值:

df <- df %>%
  group_by(id) %>%
  mutate(
    # 标记哪些行有实际值
    has_actual = !is.na(actual),
    # 为有效实际值行创建连续分组,非有效行继承上一个有效行的分组
    cycle_group = cumsum(has_actual)
  ) %>%
  # 按id和cycle_group分组,提取每组的第一个实际值(即上一个有效周期的实际值)
  group_by(id, cycle_group) %>%
  mutate(prev_actual = first(actual)) %>%
  # 回到id分组,把第一个周期的prev_actual设为NA(无上期数据)
  group_by(id) %>%
  mutate(prev_actual = ifelse(cycle_group == 1, NA, prev_actual)) %>%
  ungroup()

比如S01的2020-12是第一个周期(cycle_group=1),prev_actual为NA;2021-01到2021-03属于cycle_group=2,prev_actual就是2020-12的-0.3;2021-04到2021-06属于cycle_group=3,prev_actual就是2021-03的8.6,完美匹配季度对比逻辑。

3. 计算变动方向并整理结果

最后按照需求判断实际值和预测值的变动方向,同时处理NA情况:

df_final <- df %>%
  mutate(
    act_direction = case_when(
      # 任一值为NA则返回NA
      is.na(actual) | is.na(prev_actual) ~ NA_character_,
      actual > prev_actual ~ "increase",
      actual < prev_actual ~ "decrease",
      actual == prev_actual ~ "unchanged"
    ),
    pred_direction = case_when(
      is.na(pred) | is.na(prev_actual) ~ NA_character_,
      pred > prev_actual ~ "increase",
      pred < prev_actual ~ "decrease",
      pred == prev_actual ~ "unchanged"
    )
  ) %>%
  # 保留需要的列,并把日期转回原格式
  select(id, date, actual, pred, act_direction, pred_direction) %>%
  mutate(date = format(date, "%Y-%m"))

结果验证

查看S01的关键行:

  • 2021-03的act_direction是increase(8.6 > -0.3),pred_direction是increase(8.57 > -0.3),符合预期
  • 2021-06的act_direction是decrease(8.3 < 8.6),pred_direction是increase(8.719 > 8.6),和你给出的预期输出完全一致

内容的提问来源于stack exchange,提问作者ah bon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 10:39:11