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

Spell数据集序列重编号:R语言代码异常调试求助

Spell序列重置代码错误排查及修正

数据集

df <- structure(list(ID = c(2L, 2L, 13L, 13L, 13L, 21L, 21L, 21L, 24L, 
                            24L, 24L, 24L), mignr = c(1L, 0L, 1L, 2L, 0L, 0L, 2L, 1L, 2L, 
                                                      3L, 0L, 1L), start = c(1387L, 903L, 1357L, 1391L, 1087L, 936L, 
                                                                             1367L, 1354L, 1363L, 1392L, 908L, 1361L), end = c(1401L, 1386L, 
                                                                                                                               1390L, 1401L, 1356L, 1353L, 1399L, 1366L, 1391L, 1400L, 1360L, 
                                                                                                                               1362L), staytime = c(15L, 484L, 34L, 11L, 270L, 418L, 33L, 13L, 
                                                                                                                                                    29L, 9L, 453L, 2L)), row.names = c(NA, -12L), class = "data.frame")

需求说明

按ID分组重置Spell序列,规则如下:

  • 首个spell(mignr == 0):start=0、end=1
  • 后续spell(mignr > 0):
    • start = 前一个spell的end + 1
    • end = start + (staytime - 1)

尝试的代码

df <- df %>% 
  mutate(start = ifelse(mignr == 0, 0, start)) %>% 
  mutate(end = ifelse(mignr == 0, 1, end)) 

max_spell <- max(df$mignr)

for(i in seq_along(1:max_spell)){
  
  j <- i-1
  df <- df %>% 
    mutate(start = ifelse(mignr == i, (df[which(df$ID == ID & df$mignr == j),4]), start)) %>% 
    mutate(end = ifelse(mignr == i, start + (staytime - 1), end)) 
  
}
df

问题现象

代码仅在mignr=1时输出符合预期,mignr>1时start值不符合规则。


问题原因分析

  1. 引用原始数据而非更新后的数据:
    循环中df[which(df$ID == ID & df$mignr == j),4]调用的是循环开始前的原始df的end值,而非上一次循环更新后的end值。mutate是基于当前数据框的副本计算,无法实时引用本次循环中修改后的值。

  2. 未按ID分组处理:
    代码逻辑未对ID分组,会跨ID取mignr=j的end值,导致不同ID的Spell序列互相干扰,计算结果错误。

  3. 循环逻辑顺序错误:
    全局按mignr值批量处理,而非按每个ID内的mignr顺序(0→1→2→3)依次递推,无法保证后续Spell能正确继承前一个Spell的最新end值。


修正方案(分组递推实现)

使用dplyr分组+purrr::accumulate递推,确保每个ID内的Spell序列按顺序计算,且能实时引用前一个Spell的更新后值:

library(dplyr)
library(purrr)

df_fixed <- df %>%
  # 按ID分组,确保每个ID的Spell单独计算
  group_by(ID) %>%
  # 按mignr排序,保证0是首个Spell
  arrange(mignr) %>%
  # 初始化mignr=0的start和end
  mutate(
    start = case_when(
      mignr == 0 ~ 0,
      TRUE ~ NA_real_
    ),
    end = case_when(
      mignr == 0 ~ 1,
      TRUE ~ NA_real_
    )
  ) %>%
  # 递推计算后续Spell的start:前一个end + 1
  mutate(start = accumulate(start, ~if(is.na(.y)) .x + 1 else .y)) %>%
  # 计算end值
  mutate(end = start + staytime - 1) %>%
  ungroup() %>%
  # 恢复原数据的行顺序(可选,根据需求保留)
  slice(match(row.names(df), row.names(.)))

print(df_fixed)

代码逻辑说明

  • group_by(ID):确保每个ID的Spell序列独立计算
  • arrange(mignr):保证每个ID内的Spell按0→1→2→3的顺序排列
  • accumulate():递推生成start值,对于非0的Spell,自动取前一个Spell的end值+1
  • 最后通过start + staytime -1直接计算end,完全符合需求规则

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 11:15:44