我有一个矩阵

set.seed(1)
m <- matrix(sample(-1:1,30,replace = T,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算法的作用)

enter image description here

并将其转换为长格式,如下所示:

   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

Unit: milliseconds
             expr     min      lq      mean   median      uq     max neval
         my_fu(m)  3.3196  3.6157  4.293507  3.75735  4.0036 12.2766    30
    MrFlick_fu(m) 25.6869 26.5682 31.062887 27.22125 34.3767 60.2749    30
        one_fu(m)  3.0693  3.3389  3.507363  3.51300  3.6304  4.1176    30
   jblood94_fu(m)  1.3574  1.4510  1.621113  1.50865  1.5659  3.7355    30
 jblood94_2_fu(m)  1.0156  1.0660  1.197143  1.12360  1.2961  1.7586    30

推荐答案

第二次try :

f0 <- function(m) {
  # OP approach
  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
}

f1 <- function(m) {
  # proposed approach 1
  r <- apply(m, 2, rle)
  data.frame(
    id = unlist(lapply(r, \(x) cumsum(x[[1]])), TRUE, FALSE),
    name = rep.int(colnames(m), sapply(r, \(x) length(x[[1]]))),
    val = unlist(lapply(r, "[[", 2), TRUE, FALSE)
  )
}

f2 <- function(m) {
  # proposed approach 2
  bln <- rbind(m[-1,] != m[-nrow(m),], TRUE)
  data.frame(
    id = which(bln, TRUE)[,1],
    name = rep.int(colnames(m), colSums(bln)),
    val = m[bln]
  )
}

在更大的数据集上计时.

m <- matrix(sample(-1:1, 1e4, 1, c(1, 5, 1)), 2e3, 5, 0, list(NULL, LETTERS[1:5]))

microbenchmark::microbenchmark(
  f0 = f0(m),
  f1 = f1(m),
  f2 = f2(m),
  check = "equal"
)
#> Unit: microseconds
#>  expr      min        lq     mean    median        uq      max neval
#>    f0 1594.902 1716.3010 1926.045 1781.1510 2004.7515 7434.502   100
#>    f1  513.901  584.8005  826.936  645.8010  730.5005 6221.501   100
#>    f2  424.502  449.8510  660.544  490.2005  557.8015 6309.701   100

R相关问答推荐

保存shiny 的代码嗅探器:避免$ Symbol问题

用单个表达匹配多个替代模式

使用gggplot 2在R中重新调整面板和y轴文本大小

R:更新后无法运行控制台

如果行和大于值,则过滤

为什么横向页面会导致officeverse中的页码/节头/页脚出现问题?

在R中使用数据集名称

如何在R forestplot中为多条垂直线分配唯一的 colored颜色 ?

计算数据帧中指定值之前的行数,仅基于每行之后的future 行,单位为r

有没有一种方法可以同时对rhandsontable进行排序和从rhandsontable中删除?

按时间顺序对不同事件进行分组

为什么这个表格格罗布不打印?

`-`是否也用于数据帧,有时使用引用调用?

如何判断代码是否在R Markdown(RMD)上下文中交互运行?

通过R:文件名未正确写入[已解决]将.nc文件转换和导出为.tif文件

如何从嵌套数据中自动创建命名对象?在R中

通过比较来自多个数据框的值和R中的条件来添加新列

如何在矩阵图中按标准对数据进行分组以绘制矩阵

对一个数据帧中另一个数据帧中的值进行计数

R:水平旋转图