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

高效将非重复序列转换为长格式的R语言实现方案

矩阵RLE序列提取与长格式转换的高效实现

问题与测试数据

先生成测试矩阵:

set.seed(1)
m <- matrix(sample(-1:1, 30, replace = TRUE, prob = c(1,5,1)),
            ncol = 3, dimnames = list(NULL, LETTERS[1:3]))

生成的矩阵内容:

m
       A  B  C
 [1,]  0  0 -1
 [2,]  0  0  0
 [3,]  0  0  0
 [4,] -1  0  0
 [5,]  0  1  0
 [6,] -1  0  0
 [7,] -1  1  0
 [8,]  0 -1  0
 [9,]  0  0 -1
[10,]  0  1  0

需求:提取每列中游程编码(RLE)对应的非重复序列,转换为如下长格式数据框:

id name val
1   3    A   0
2   4    A  -1
3   5    A   0
4   7    A  -1
5  10    A   0
6   4    B   0
7   5    B   1
8   6    B   0
9   7    B   1
10  8    B  -1
11  9    B   0
12 10    B   1
13  1    C  -1
14  8    C   0
15  9    C  -1
16 10    C   0

现有实现效率极低,需处理2000行5列的小型矩阵,但要重复运行数十万次,因此需要最优解决方案。

原始低效实现

rid <- apply(m, 2, \(colum) cumsum(rle(colum)$length))

long_df <- NULL
for(Name in names(rid)){
  df <- cbind.data.frame(id   = rid[[Name]],
                         name = Name, 
                         val  = m[rid[[Name]], Name]) 
  long_df <- rbind.data.frame(long_df, df)
}

long_df

基准测试结果(单位:毫秒)

函数名最小值下四分位数平均值中位数上四分位数最大值测试次数
my_fu(m)3.31963.61574.2935073.757354.003612.276630
MrFlick_fu(m)25.686926.568231.06288727.2212534.376760.274930
one_fu(m)3.06933.33893.5073633.513003.63044.117630
jblood94_fu(m)1.35741.45101.6211131.508651.56593.735530
jblood94_2_fu(m)1.01561.06601.1971431.123601.29611.758630

最优解决方案

根据基准测试,jblood94_2_fu是效率最高的实现,核心通过向量化操作+一次性合并避免循环拼接的开销,代码如下:

jblood94_2_fu <- function(m) {
  # 对每列计算RLE的结束位置和对应值,直接生成子数据框
  rle_results <- apply(m, 2, function(x) {
    r <- rle(x)
    data.frame(id = cumsum(r$lengths), val = r$values)
  })
  # 合并所有列的结果,添加列名标识
  do.call(rbind, Map(cbind, name = names(rle_results), rle_results))
}

效率提升关键点

  1. 避免循环中重复调用rbind.data.frame:每次拼接都会复制整个数据框,几十万次运行时开销呈指数增长;改用do.call(rbind, ...)一次性合并,底层优化更高效
  2. 直接从RLE结果取值:无需二次索引原矩阵,减少内存访问开销
  3. 用Map替代显式循环:简化代码的同时,利用R的内置向量化优化

内容的提问来源于stack exchange,提问作者mr.T

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 18:58:19