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

如何用tidyverse更高效地为连续非NA值创建游程ID?

为连续非NA值创建游程ID的简洁tidyverse实现

给定如下数据:

df <- data.frame(
  ID = 1:10,
  Q_segment = c(NA, "tcu_pol","frg", NA, NA, "tcu_wh","tcu_wh", NA, "xy","m,n")
)

需求是为Q_segment中的连续非NA值生成游程ID,NA对应的位置保留NA。现有dplyr实现逻辑复杂,以下是几种更简洁高效的tidyverse方案:

方案一:consecutive_id直接处理

library(dplyr)

df %>%
  mutate(Q_sequence = if_else(is.na(Q_segment), NA_integer_, 
                              consecutive_id(is.na(Q_segment))))

核心逻辑:is.na(Q_segment)生成一组布尔值,连续非NA对应连续的FALSE,consecutive_id为这组连续相同的布尔值分配统一ID,最后通过if_else将NA位置的结果设为NA,非NA位置保留游程ID。

方案二:cumsum标记非NA段起始

df %>%
  mutate(Q_sequence = if_else(is.na(Q_segment), NA_integer_, 
                              cumsum(!is.na(Q_segment) & lag(is.na(Q_segment), default = TRUE))))

核心逻辑:通过!is.na(Q_segment) & lag(is.na(Q_segment), default = TRUE)判断当前非NA行是否是一段连续非NA的起始(前一行是NA或为第一行),用cumsum对这些起始点计数,连续非NA行自然共享同一个计数。

方案三:结合data.table的rleid(更直观)

如果允许引入data.table包,rleid函数专门用于生成游程ID,实现更简洁:

library(dplyr)
library(data.table)

df %>%
  mutate(Q_sequence = if_else(is.na(Q_segment), NA_integer_, rleid(is.na(Q_segment))))

rleid的作用和consecutive_id类似,直接为连续相同的布尔值分配ID,后续逻辑和方案一一致。

以上三种方案都能得到目标输出:

ID Q_segment Q_sequence
1   1      <NA>         NA
2   2   tcu_pol          1
3   3       frg          1
4   4      <NA>         NA
5   5      <NA>         NA
6   6    tcu_wh          2
7   7    tcu_wh          2
8   8      <NA>         NA
9   9        xy          3
10 10       m,n          3

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 21:35:15