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

在R语言中基于时间与第三列传值至下一行并创建smk_R列

解决R语言中跨Type行传递吸烟状态的问题

我来帮你搞定这个需求!要实现把Type 0行的吸烟状态传递到同ID下后续最近的Type 1行,并标记两次Type 1评估间是否吸烟,用tidyverse工具链(dplyr+tidyr)就能轻松实现,逻辑清晰还容易维护。

核心思路拆解

  1. 先确保数据顺序正确:每个ID内的行必须按时间从小到大排序,不然状态传递会完全混乱。
  2. 给Type 1锚点分组:把每一个Type 1行,加上它之后到下一个Type 1行之前的所有Type 0行,归为同一个分组。
  3. 组内判断吸烟状态:在每个分组里检查是否存在smk=1的记录,只要有一次吸烟,就给该分组对应的Type 1行标记smk_R=1,否则为0。

代码实现(附示例数据)

首先我们先模拟一份贴合你需求的示例数据,方便你测试:

library(tidyverse)

# 生成示例数据:包含ID、时间、类型、吸烟状态
set.seed(123)
df <- tibble(
  ID = rep(1:3, each = 5),
  time = rep(1:5, 3),
  Type = case_when(
    ID == 1 & time %in% c(1,4) ~ 1,  # ID1的锚点是时间1和4
    ID == 2 & time %in% c(2,5) ~ 1,  # ID2的锚点是时间2和5
    ID == 3 & time %in% c(1,3,5) ~ 1,# ID3有三个锚点
    TRUE ~ 0
  ),
  smk = sample(c(0,1), 15, replace = TRUE)
)

接下来是核心处理代码:

df_final <- df %>%
  # 按ID分组,强制按时间排序
  group_by(ID) %>%
  arrange(time, .by_group = TRUE) %>%
  # 给每个Type1锚点创建分组:每遇到一个Type1,组号+1
  mutate(type1_group = cumsum(Type == 1)) %>%
  # 按ID+分组号再次分组,判断组内是否有吸烟记录
  group_by(ID, type1_group) %>%
  mutate(
    # 组内只要有smk=1,就标记为1;否则0
    smk_R = ifelse(any(smk == 1), 1, 0),
    # 只在Type1行保留标记,Type0行设为NA(可根据需求调整)
    smk_R = ifelse(Type == 1, smk_R, NA)
  ) %>%
  ungroup()

# 查看处理结果
print(df_final, n = 15)

关键代码解释

  • arrange(time, .by_group = TRUE):这一步是基础中的基础!必须保证每个ID内的行按时间顺序排列,否则分组和状态传递都会出错。如果你的时间是日期格式,这个排序逻辑同样适用。
  • type1_group = cumsum(Type == 1):用累加和生成分组ID,比如第一个Type1行是组1,后面的Type0都属于组1,直到下一个Type1出现,组号自动变成2,完美把两次Type1之间的行归为一组。
  • any(smk == 1):检查分组内所有行的吸烟状态,只要有一次吸烟记录,就给该分组对应的Type1行标记为1,完全符合你"判断两次Type1评估间是否吸烟"的需求。
  • 最后那个ifelse:如果不需要保留Type0行的smk_R,就把它们设为NA;如果需要保留传递的状态,也可以改成保留对应的值,灵活调整即可。

特殊情况处理

  • 如果两个Type1行紧挨着(中间没有Type0):此时该分组只有这个Type1行,smk_R会直接取它自己的smk值,逻辑完全合理。
  • 如果需要传递的是最后一次Type0的吸烟状态(而不是只要有吸烟就标记):可以把any(smk ==1)改成last(smk[Type==0]),再处理NA的情况就行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:41:01