【问题标题】:Merge vectors with different length into a matrix one after the other将不同长度的向量一个接一个地合并成一个矩阵
【发布时间】:2017-12-13 11:32:09
【问题描述】:

假设我们有以下三个向量。

L = c("1", "3")
K = c("2", "9", "2:9")
S = c("7")

有没有办法将它们组合成一个类似于上面的矩阵?

L    K    S
1    0    0
3    0    0
0    2    0
0    9    0
0    2:9  0
0    0    7

谢谢。

【问题讨论】:

    标签: r matrix vector


    【解决方案1】:
    library(dplyr)
    
    L = c("1", "3")
    K = c("2", "9", "2:9")
    S = c("7")
    
    Ltable <- tibble(L=L)
    Ktable <- tibble(K=K)
    Stable <- tibble(S=S)
    JoinedMatrix <- Ltable %>% bind_rows(Ktable) %>% bind_rows(Stable) %>% as.matrix() 
    JoinedMatrix[which(is.na(JoinedMatrix))] <- "0"
    

    bind_rows from dplyr 允许您将数据帧(或小标题)绑定在一起。由于三个 tibbles 具有不同名称的列,因此它们在连接后保留为不同的列,用NA 填充缺失的字段。之后,我们只需将所有NAs 替换为0,就完成了。

    > JoinedMatrix
         L   K     S  
    [1,] "1" "0"   "0"
    [2,] "3" "0"   "0"
    [3,] "0" "2"   "0"
    [4,] "0" "9"   "0"
    [5,] "0" "2:9" "0"
    [6,] "0" "0"   "7"
    

    【讨论】:

      【解决方案2】:

      这是一个想法。首先我们创建一个包含所有向量的列表,然后创建一个矩阵,其行数等于向量的所有元素的总和,列数等于向量的数量。然后我们使用mapply 将(我们的列表中的)第一个向量的元素与矩阵的第一列相匹配。分别与第二个和第三个向量和列相同。然后我们使用它(一个逻辑矩阵)将矩阵中所有剩余的不匹配元素转换为 0。

      l1 <- list(L, K, S)
      m1 <- matrix(unlist(l1), nrow = sum(lengths(l1)), ncol = length(l1))
      m1[!mapply(`%in%`, as.data.frame(m1), l1)] <- 0
      
      m1
      #     [,1] [,2]  [,3]
      #[1,] "1"  "0"   "0" 
      #[2,] "3"  "0"   "0" 
      #[3,] "0"  "2"   "0" 
      #[4,] "0"  "9"   "0" 
      #[5,] "0"  "2:9" "0" 
      #[6,] "0"  "0"   "7"
      

      为了解决您的评论并将其升级为也适用于出现在多个向量中的相同值,我们遵循相同的逻辑,但我们根据每个向量的累积序列对矩阵每一列的索引执行此操作。由于这有点复杂,我们可以将它全部放在一个接受向量列表作为输入的函数中,即

      create_mat <- function(list){
        m1 <- matrix(unlist(list), nrow = sum(lengths(list)), ncol = length(list))
        m2 <- matrix(seq(nrow(m1)), ncol = ncol(m1), nrow = nrow(m1))
        l2 <- lapply(lengths(list), seq)
        v2 <- c(0, head(cumsum(lengths(list)), -1))
        l2 <-  Map(`+`, l2, v2)
        m1[!mapply(`%in%`, as.data.frame(m2), l2)] <- 0
        return(m1)
      }
      
      # Test with some values being same for multiple vectors,
      M = c("1", "3")
      N = c("1", "9", "2:9")
      P = c("3")
      
      create_mat(list(M, N, P))
      
      #     [,1] [,2]  [,3]
      #[1,] "1"  "0"   "0" 
      #[2,] "3"  "0"   "0" 
      #[3,] "0"  "1"   "0" 
      #[4,] "0"  "9"   "0" 
      #[5,] "0"  "2:9" "0" 
      #[6,] "0"  "0"   "3" 
      

      【讨论】:

      • 对不起这个问题,它可能在不同的线程中,但我不确定。我做了你写的,它工作得很好。但现在我想添加更多内容。有没有办法获取这个输出并创建一个新矩阵,其中每个实例 (L,K,S) 的行的所有可能组合由两个 (L , K) , (L,S), (K,S) ?例如this 之类的东西。其实我试过这个,但添加了很多相同的想法g = as.list(data.frame(m1)) expand.grid(g)
      • 好的。最后我使用了unique(expand.grid(g)) 并工作了。
      • 我只是意识到,如果初始向量相同,您的代码似乎无法按预期工作。你能想出一个解决办法吗?
      • 非常感谢。虽然我也遇到了另一个问题,但它与资源有关。我意识到,例如,如果我们必须在主列表中列出项目,其中第一个 on 只有一个元素 c("0") 而另一个有大约 16000 个元素 c(1:16000) ,通过执行此函数,您会耗尽系统的内存R 得到一个致命错误。您是否认为有一种方法可以使其对资源更加友好? P.S 我在 4GB 内存的 PC 上运行它
      【解决方案3】:

      这是另一种方法:首先创建一个 0 矩阵,然后使用两个索引向量 k1:l,在正确的位置输入值。

      l = length(c(L,K,S))
      k = rep(1:3,times=c(length(L),length(K),length(S)))
      m = matrix(0,ncol=3,nrow=l)
      m[cbind(1:l,k)] = c(L,K,S)
           [,1] [,2]  [,3]
      [1,] "1"  "0"   "0" 
      [2,] "3"  "0"   "0" 
      [3,] "0"  "2"   "0" 
      [4,] "0"  "9"   "0" 
      [5,] "0"  "2:9" "0" 
      [6,] "0"  "0"   "7" 
      

      编辑:对于可以更好地泛化到更多输入向量的版本,根据@DavidArenburg 的评论,您可以这样做:

      l = list(L,K,S)
      len = length(unlist(l))
      k = rep(seq_along(l), lengths(l))
      m = matrix(0, nrow=len, ncol=length(l))
      m[cbind(1:len, k)] = unlist(l)
      

      【讨论】:

      • @DavidArenburg 我同意,您的版本可以更好地概括更多输入向量。我将编辑我的答案以包括您的 cmets。
      • @all。非常感谢,但从效率和耗时的角度来看,我应该更喜欢其中一个吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-18
      • 1970-01-01
      • 2019-11-18
      • 1970-01-01
      • 2013-09-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多