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

如何用R(dplyr)按校ID分组,为连续年级块生成递增序号

用dplyr生成连续相同grade区块的分组编号new_id

需求:基于包含schoolid(校ID)和grade(年级)列的数据框,生成新列new_id。规则为:在每个schoolid分组内,对连续出现的相同grade的区块从1开始递增编号,同一区块内所有行的new_id值相同。

目标数据示例

structure(list(schoolid = c(201L, 201L, 201L, 201L, 201L, 201L, 201L, 201L, 201L, 201L, 201L, 201L, 201L, 202L, 202L, 202L, 202L, 202L, 202L, 202L, 202L, 202L), grade = c(3L, 3L, 4L, 4L, 5L, 5L, 3L, 3L, 5L, 5L, 5L, 3L, 3L, 3L, 3L, 4L, 4L, 5L, 5L, 3L, 4L, 4L), new_id = c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L)), row.names = c(NA, 22L), class = "data.frame")

错误尝试代码

data %>%
  group_by(schoolid, grade) %>%
  mutate(new_id = 1:n())

该代码的问题在于:同时按schoolid和grade分组会将所有同校同年级的行归为一组,忽略了「连续出现」的要求,生成的是组内行号而非连续区块的编号。

正确实现方法

核心思路是在每个schoolid分组内,先识别连续grade区块的边界,再通过累加边界标记生成连续编号:

library(dplyr)

data %>%
  group_by(schoolid) %>%
  mutate(
    # 标记当前行与前一行grade是否不同,首行默认与自身相同(标记为FALSE)
    block_change = grade != lag(grade, default = first(grade)),
    # 累加边界标记得到区块编号,+1让编号从1开始
    new_id = cumsum(block_change) + 1
  ) %>%
  ungroup()

代码解释

  1. group_by(schoolid):仅按校ID分组,确保每个学校内独立处理连续区块
  2. block_change:通过lag()获取前一行的grade,与当前行比较,当grade变化时标记为TRUE(即区块边界)
  3. cumsum(block_change):累加边界标记,每次遇到TRUE(边界)时数值+1,这样同一连续区块内的数值相同
  4. +1:将初始的0编号转为从1开始

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 03:15:38