R语言如何将向量按区间替换为升序编号(支持保留间隔缺口)
R向量连续区间编号实现方法
需求1:连续相同值块顺次编号(忽略原数值间隔)
该场景要求每遇到一段连续重复的数值就分配一个逐次+1的编号,不考虑不同块之间原数值的差值大小。
示例输入:
x <- c(5, 5, 5, 7, 7, 7, 9, 11, 11, 11, 15, 15, 15, 17, 17, 17, 17)
对应期望输出:
y <- c(1, 1, 1, 2, 2, 2, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6)
实现方式
- 第三方包快速实现:直接用
data.table包的rleid()函数,这是专门为连续重复值分组设计的函数,一行代码即可得到结果:
library(data.table) y <- rleid(x)
- 原生R实现,无需安装额外包:通过判断相邻位置是否发生值变化,累加变化次数得到编号:
y <- cumsum(c(1, diff(x) != 0))
两种方式运行得到的结果和期望输出完全一致。
需求2:编号保留原数值的间隔缺口
该场景要求不同块之间的编号差值和原数值的差值保持一致,第一个数值块编号从1开始。
示例输入:
x <- c(5, 5, 7, 7, 8, 8, 9)
对应期望输出:
y <- c(1, 1, 3, 3, 4, 4, 5)
逻辑说明:第一个值块(数值5)编号为1;下一个值块数值为7,和前一个块差值为2,因此编号为1+2=3;后续值块数值为8,和前一块差值为1,编号为3+1=4;最后一个值块数值为9,和前一块差值为1,编号为4+1=5,和预期匹配。
实现方式
原生R即可实现,逻辑是先拆分连续值块,按块计算对应编号后再映射回原向量:
# 生成连续值块ID block_id <- cumsum(c(1, diff(x) != 0)) # 提取每个值块对应的唯一数值 block_value <- x[!duplicated(block_id)] # 按数值差计算每个块的对应编号 block_label <- cumsum(c(1, diff(block_value))) # 将块编号匹配到原向量的每个位置 y <- block_label[block_id]
运行结果和期望输出完全一致。如果习惯用data.table,也可以用更简洁的链式写法实现相同效果。
内容的提问来源于stack exchange,提问作者Orangemarmalade
相关产品推荐
相关产品推荐

