【问题标题】:Extracting multiple rows from a matrix depending on ID given by a vector根据向量给出的 ID 从矩阵中提取多行
【发布时间】:2015-11-20 06:25:18
【问题描述】:

假设我们有一个包含 3 列的矩阵 m 和一个带有行标识的向量 id

m <- matrix(c(1,1,2,1,2,3,2,2,2,3,3,4,6,7,7,
          2,2,2,4,4,5,8,9,9),ncol=3,byrow=T)

# m
#     [,1] [,2] [,3]
#[1,]    1    1    2
#[2,]    1    2    3
#[3,]    2    2    2
#[4,]    3    3    4
#[5,]    6    7    7
#[6,]    2    2    2
#[7,]    4    4    5
#[8,]    8    9    9

id <- c(1,2,3,4,5,1,4,5)

mid 中提取行的最快方法是什么?

因此,我想为id 中的每个唯一标识符提供一个向量。比如:

##[1] 1 1 2 2 2 2
##[2] 1 2 3
##[3] 2 2 2
##[4] 3 3 4 4 4 5
##[5] 6 7 7 8 9 9

我相当糟糕的解决方案对于我的目的来说太慢了:

pts_list <- list()
for (i in unique(id)){
  pts_list[[i]] <- as.vector(t(m[id==i,]))
}
pts_list

这里有一个测试速度的小脚本(这真的很难看……):

pts_list <- list()
m2 <- cbind(m,m,m,m)
m3 <- rbind(m2,m2,m2,m2,m2,m2,m2,m2,m2,m2)
m4 <- rbind(m3,m3,m3,m3,m3,m3,m3,m3,m3,m3)
m5 <- rbind(m4,m4,m4,m4,m4,m4,m4,m4,m4,m4)
m6 <- rbind(m5,m5,m5,m5,m5,m5,m5,m5,m5,m5)
id6 <- rep(1:8000,10)

system.time(
  for (i in unique(id6)){
    pts_list[[i]] <- as.vector(t(m6[id6==i,]))
  }
)

#   user  system elapsed 
#  8.094   1.524   9.617

有什么建议吗?

【问题讨论】:

    标签: r for-loop matrix vectorization


    【解决方案1】:

    如果您不关心值顺序,您可以简单地做

    split(m, id)
    # $`1`
    # [1] 1 2 1 2 2 2
    # 
    # $`2`
    # [1] 1 2 3
    # 
    # $`3`
    # [1] 2 2 2
    # 
    # $`4`
    # [1] 3 4 3 4 4 5
    # 
    # $`5`
    # [1] 6 8 7 9 7 9
    

    如果你在乎,你可以把它和lapply结合起来

    lapply(split(as.data.frame(m), id), function(x) c(t(x)))
    # $`1`
    # [1] 1 1 2 2 2 2
    # 
    # $`2`
    # [1] 1 2 3
    # 
    # $`3`
    # [1] 2 2 2
    # 
    # $`4`
    # [1] 3 3 4 4 4 5
    # 
    # $`5`
    # [1] 6 7 7 8 9 9
    

    【讨论】:

    • 太棒了,谢谢。那是闪电般的速度。为了速度起见,我很高兴我的数字杂乱无章。似乎第一个和最后一个数字仍然存在,这就是我真正需要的。
    【解决方案2】:

    lapply 应该比for 提供一点速度增益

    > system.time(
         for (i in unique(id6)){
             pts_list[[i]] <- as.vector(t(m6[id6==i,]))
         }
     )
       user  system elapsed 
       4.74    0.67    5.45 
    
    > system.time(
         pts_list <- lapply(unique(id6), function(x) as.vector(t(m6[id6==x,])))
      )
       user  system elapsed 
       3.92    0.66    4.65 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-01
      • 2022-01-04
      • 1970-01-01
      相关资源
      最近更新 更多