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

R语言多状态数据中删失时间与事件指示器的tidyverse实现

用tidyverse高效实现状态事件的双变量计算(适配大数据集)

问题背景

现有R数据框包含3个中间状态(A、B、C)和2个终末状态(D、E),每个状态对应Event(事件标识,0/1)和EventTime(事件发生时间)两列。需生成两个计算列:

  1. Var1:优先级规则为:
    • 若D/E的Event存在1,返回D/E中第一个Event=1对应的EventTime;
    • 否则若A/B/C的Event存在0,返回A/B/C中第一个Event=0对应的EventTime;
    • 若前两个条件都不满足(A/B/C无0且D/E全为0),返回D/E中第一个Event=0对应的EventTime。
  2. Var2:若D/E的Event存在1则返回0,否则返回1。

之前用apply实现但效率不足,以下提供基于tidyverse的向量化/分组优化方案,适配大数据集。


解决方案:tidyverse向量化分组实现

核心思路是将宽格式数据转为长格式,利用分组操作批量处理每行的状态事件,避免逐行循环(如rowwise/pmap)带来的性能损耗。

1. 构造示例数据

library(tidyverse)

set.seed(123)
df <- tibble(
  A_Event = sample(c(0,1), 10, replace = TRUE),
  A_EventTime = runif(10, 1, 10),
  B_Event = sample(c(0,1), 10, replace = TRUE),
  B_EventTime = runif(10, 1, 10),
  C_Event = sample(c(0,1), 10, replace = TRUE),
  C_EventTime = runif(10, 1, 10),
  D_Event = sample(c(0,1), 10, replace = TRUE),
  D_EventTime = runif(10, 1, 10),
  E_Event = sample(c(0,1), 10, replace = TRUE),
  E_EventTime = runif(10, 1, 10)
)

2. 数据转长格式并分组计算

# 转长格式,保留行标识以便后续合并
df_long <- df %>%
  mutate(row_id = row_number()) %>%
  pivot_longer(
    cols = -row_id,
    names_to = c("state", ".value"),
    names_pattern = "(.)_(Event|EventTime)"
  ) %>%
  # 按规则排序:先终末状态D/E,再中间状态A/B/C,确保优先匹配高优先级条件
  arrange(row_id, factor(state, levels = c("D", "E", "A", "B", "C")))

# 分组计算Var1和Var2
result_df <- df_long %>%
  group_by(row_id) %>%
  mutate(
    # 判断是否存在终末状态事件(D/E有Event=1)
    has_terminal_event = any(state %in% c("D", "E") & Event == 1),
    Var2 = as.integer(!has_terminal_event)
  ) %>%
  # 按优先级筛选符合条件的行
  filter(
    if (has_terminal_event) {
      state %in% c("D", "E") & Event == 1
    } else {
      # 先匹配中间状态的0,再匹配终末状态的0
      (state %in% c("A", "B", "C") & Event == 0) | (state %in% c("D", "E") & Event == 0)
    }
  ) %>%
  # 取第一个符合条件的时间(因已排序,第一个即为优先级最高的结果)
  slice_head(n = 1) %>%
  rename(Var1 = EventTime) %>%
  select(row_id, Var1, Var2) %>%
  ungroup()

# 合并回原数据框
final_df <- df %>%
  mutate(row_id = row_number()) %>%
  left_join(result_df, by = "row_id") %>%
  select(-row_id)

性能优势说明

  • 避免了apply/rowwise的逐行循环,利用pivot_longer的向量化转换和dplyr的分组优化,在大数据集(十万级以上行)中性能提升明显;
  • 通过提前排序确保筛选时直接取第一个匹配项,无需额外的位置计算逻辑,代码更简洁易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 21:54:54