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

在R中跨24个月对齐多年份数据的技术问询

月度观测数据跨两年对齐解决方案

示例数据集

提供的示例数据集如下:

data <- structure(list(id = c(11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 
11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 
11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 22L, 22L, 22L, 22L, 22L, 
22L, 22L, 22L, 22L, 22L, 22L, 22L, 22L, 22L, 22L, 22L, 22L), 
    month = c(8L, 8L, 8L, 9L, 10L, 10L, 10L, 11L, 11L, 11L, 11L, 
    12L, 12L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 3L, 3L, 6L, 6L, 8L, 
    8L, 8L, 9L, 11L, 1L, 1L, 2L, 2L, 6L, 7L, 9L, 9L, 12L, 12L, 
    3L, 3L, 6L, 7L, 8L, 9L, 9L), month_new = c(8L, 8L, 8L, 9L, 
    10L, 10L, 10L, 11L, 11L, 11L, 11L, 12L, 12L, 13L, 13L, 13L, 
    13L, 13L, 14L, 14L, 15L, 15L, 18L, 18L, 20L, 20L, 20L, 21L, 
    23L, 1L, 1L, 2L, 2L, 6L, 7L, 9L, 9L, 12L, 12L, 15L, 15L, 
    18L, 19L, 20L, 21L, 21L)), class = "data.frame", row.names = c(NA, 
-46L))

需求说明

  • 按每个id分组处理数据,实现跨两年(24个月)的月份对齐
  • 第一年的月份保持原值不变
  • 当观测中出现过12月后,后续所有月份需加12

现有代码问题

原代码在处理重复月份、跳月场景下无法得到正确结果:

output_desired <- locs %>% 
  group_by(ptt) %>%
  mutate(new = first(month_num) - 1 + as.integer(factor(month_num, unique(month_num))))

错误输出示例

id month month_new
 1    11     8         8
 2    11     8         8
 ...

期望正确输出

正确的输出结果结构如下:

output_desired <- structure(list(id = c(11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 
11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 
11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 22L, 22L, 22L, 22L, 22L, 
22L, 22L, 22L, 22L, 22L, 22L, 22L, 22L, 22L, 22L, 22L, 22L), 
    month = c(8L, 8L, 8L, 9L, 10L, 10L, 10L, 11L, 11L, 11L, 11L, 
    12L, 12L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 3L, 3L, 6L, 6L, 8L, 
    8L, 8L, 9L, 11L, 1L, 1L, 2L, 2L, 6L, 7L, 9L, 9L, 12L, 12L, 
    3L, 3L, 6L, 7L, 8L, 9L, 9L), month_new = c(8L, 8L, 8L, 9L, 
    10L, 10L, 10L, 11L, 11L, 11L, 11L, 12L, 12L, 13L, 13L, 13L, 
    13L, 13L, 14L, 14L, 15L, 15L, 18L, 18L, 20L, 20L, 20L, 21L, 
    23L, 1L, 1L, 2L, 2L, 6L, 7L, 9L, 9L, 12L, 12L, 15L, 15L, 
    18L, 19L, 20L, 21L, 21L)), class = "data.frame", row.names = c(NA, 
-46L))

部分正确输出展示:

id month month_new
1  11     8         8
2  11     8         8
 ...

解决方案

使用dplyr分组处理,核心逻辑是先标记每个id下是否已经出现过12月,再根据标记计算新月份:

library(dplyr)

data_processed <- data %>%
  group_by(id) %>%
  mutate(
    # 标记当前行及之前是否出现过12月
    passed_december = cumsum(month == 12) > 0,
    # 根据标记计算新月份:未过12月则保留原值,过了则加12
    month_new = ifelse(passed_december, month + 12, month)
  ) %>%
  ungroup()

# 验证结果是否与期望一致
all.equal(data_processed$month_new, output_desired$month_new)

逻辑说明

  1. 分组:按id分组,确保每个个体的处理独立
  2. 标记12月出现状态:用cumsum(month == 12)累计12月出现的次数,只要累计次数大于0,就说明已经过了12月
  3. 计算新月份:对已经过12月的行,月份加12;未过的保持原值
  4. 去分组:处理完成后取消分组,方便后续操作

这个方案可以正确处理重复月份、跳月的场景,完全匹配需求中的输出要求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 21:21:59