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

R语言dplyr处理纵向数据:实现迁移累计计数、标记事件前后年份

问题修正方案

可直接运行的修正后代码

library(dplyr)
set.seed(123)
df <- tibble(
  id = c(1, 2, 3, 4, 5,     
         1, 2, 3, 5, 6, 7,  
         2, 3, 4, 6, 7, 8,  
         1, 2, 3, 4, 6, 7, 8   
         ), 
  year = c(rep(2009, 5), 
           rep(2010, 6), 
           rep(2011, 6), 
           rep(2012, 7)),
  age = c(0, 0, 0, 0, 0,
          1, 1, 1, 1, 0, 1,
          2, 2, 2, 1, 2, 2,
          3, 3, 3, 3, 2, 3, 3),
  town = c("0", "0", "2", "0", "0",
          "1", "2", "1", "3", "0", "1",
          "3", "1", "4", "1", "2", "1",
          "4", "2", "2", "1", "2", "1", "5")
)

df3 <- df %>%
  arrange(id, year) %>%
  group_by(id) %>%
  mutate(first_year = min(year)) %>%
  mutate(first_town = list(town[year==first_year])) %>%
  mutate(flag_move = as.numeric(year != first_year & !(town %in% unlist(first_town)) & town !="")) %>%
  mutate(flag_first_move = (flag_move==1 & as.numeric(!duplicated(flag_move)))) %>%
  mutate(moved = case_when(
    is.na(lag(town)) ~ 0,
    town != lag(town)  ~ 1,
    TRUE  ~ 0
  )) %>%
  mutate(flag_cum_move = cumsum(moved))

df4 <- df3 %>%
  group_by(id) %>%
  filter(any(flag_first_move == 1)) %>%
  mutate(
    move_years = list(year[moved == 1]),
    year_before = as.integer(year %in% (unlist(move_years) - 1)),
    year_after = as.integer(year %in% (unlist(move_years) + 1))
  ) %>%
  select(-move_years)

修正逻辑说明

1. 累计迁移计数flag_cum_move实现

原写法错误点:

  • 用diff(moved)生成的向量长度比分组内观测数少1,手动补0的逻辑没有对齐迁移事件触发节点,会把非迁移的数值波动计入计数。
    修正逻辑:
  • 已生成的moved列本身已正确标记每一次居住地变动:迁移发生对应行取值为1,其余为0。直接按分组对moved做累计求和cumsum(moved),就能得到每个观测时点对应的个体累计迁移次数,初始未迁移状态为0,每发生一次迁移计数加1,完全匹配需求。
    额外优化:原moved生成逻辑没有显式处理每个id首行lag(town)返回NA的情况,显式加判断is.na(lag(town)) ~ 0避免隐式类型转换的潜在问题;排序改为先按id再按year,保证分组内时序正确。

2. 多次迁移下的迁移前后年份标记

原写法错误点:

  • 当个体存在多次迁移时,year[moved == 1]返回长度大于1的向量,直接和逐行的标量year做差会触发R的向量循环对齐规则,长度不匹配时输出结果完全错乱,同时抛出警告。
    修正逻辑:
  • 先提取每个个体所有迁移发生的年份存入临时列表列,对每一行的年份,判断是否落在「所有迁移年份减1」的集合中(即迁移前一年),或落在「所有迁移年份加1」的集合中(即迁移后一年),用%in%做逐元素判断,无论个体有多少次迁移都能正确标记,不会出现长度不匹配问题。
  • 该逻辑自动适配连续迁移场景:例如个体2010、2011连续迁移,2010年会被标记为2011年迁移的year_before,2011年会被标记为2010年迁移的year_after,符合时序逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 19:36:46