【问题标题】:Create a matrix out of several vectors用几个向量创建一个矩阵
【发布时间】:2015-01-30 17:32:33
【问题描述】:

我有几个二维向量,其中第一列是索引(例如“时间戳”),第二列是值。

在每个 for 循环中,我得到这些向量中的一个,并且我想将它们全部合并到一个大的 2D 矩阵中,其中第一列是索引,而每一列都是与这些原始向量不同的值。

例如:

v1 <- matrix(c(seq(1:10), rnorm(10)), nrow = 10, ncol = 2)
v2 <- matrix(c(1, 2, 3, 6, 7, 8, 9, rnorm(7)), nrow = 7, ncol = 2)
v3 <- matrix(c(11, 12, rnorm(2)), nrow = 2, ncol = 2)

我想要的结果是一个 12x4 矩阵:

第一列是 1:12,第二列是 v1 根据时间戳 1:10 的值,第三列是 v2 仅在位置 1、2、3、6、7、8、9 的值,第四列column 是仅在第 11、12 位的 v3 的值。 在没有可用值的地方将放置 NULL。

请注意,我希望它们都根据它们的时间戳合并。

【问题讨论】:

  • 与您的问题无关,但您没有在正确的位置关闭括号以创建 v2 和 v3...
  • 另一件事:NULL 不能放在矩阵中。 NULL 表示不能放在数组中的 NULL 对象。您可能想填写 NA。为了说明差异,请尝试代码c(1, NA, NULL)

标签: r matrix merge


【解决方案1】:

如果生成的所有“向量”都称为“vi”,i 是一个数字,你可以这样做:

# get the names of all the "vectors" generated :
list_vec<-ls(pattern="^v\\d+$")

# get all unique timestamps (all unique values from 1st column of the different "vectors")
unique_timestamp<-unique(unlist(sapply(list_vec,function(x){get(x)[,1]})))

# create the matrix that will contain all results :
new_mat<-matrix(,nrow=length(unique_timestamp),ncol=length(list_vec)+1)
new_mat[,1]<-sort(unique_timestamp)
colnames(new_mat)<-c("timestamp",list_vec)

# finally, fill the matrix with the values in second column of the different "vectors", with respect to the timestamps    
new_mat[,2:ncol(new_mat)]<-sapply(list_vec,function(x,mat){
                                              x<-get(x)
                                              x[match(mat[,1],x[,1]),2]
                              },new_mat)

> new_mat
      timestamp          v1         v2         v3
 [1,]         1 -0.95467687 -1.2764675         NA
 [2,]         2 -0.82596352  0.8011679         NA
 [3,]         3  0.20617686  0.3820669         NA
 [4,]         4 -0.09122235         NA         NA
 [5,]         5  0.42571662         NA         NA
 [6,]         6 -0.11503517  1.2128891         NA
 [7,]         7  0.64854445  0.4053852         NA
 [8,]         8  0.22632685  0.7690795         NA
 [9,]         9 -1.52236147  0.3290537         NA
[10,]        10  0.19791912         NA         NA
[11,]        11          NA         NA -2.0296883
[12,]        12          NA         NA  0.1624292

【讨论】:

  • 感谢您的回答。但正如我所说,向量是在 for 循环中给出的,我事先不知道有多少或它们的长度/时间戳。因此我需要更通用的东西,在每次迭代时将新向量添加到矩阵中,或者扩大矩阵,或者将向量定位在矩阵中的正确时间戳中。
  • @user3370773,根据我的回答,您可以在 for 循环结束后立即创建矩阵。你不需要知道有多少向量,或者它们的长度,只是它们的名字“看起来像”。我不认为扩大矩阵是一个好的解决方案,因为 R 将分配越来越多的内存而不在每一步释放它(我的意思是,例如,R 为 2x20 矩阵分配内存,然后为 3x25 矩阵分配内存,但内存为2x20 矩阵不会被释放)。
  • 非常感谢。因此,您的建议是在所有向量上运行 for 循环并用已知名称调用它们。循环完成后,我应该根据所有保存的向量创建矩阵。对吗?
  • @user3370773,不客气,是的,我会这样做。您可以将您的向量称为“v1”、“v2”...或“vector1”等(但在这种情况下,您必须在我的答案的ls 调用中修改模式),即使用相同的模式,因此只需一次调用即可轻松“捕获”它们,然后,一旦每个向量都“存在”,您只需创建全局矩阵。
  • 你能再帮我一件小事,那就是如何调用具有相同模式名称的向量。我通常会写类似 v
【解决方案2】:

这是另一种选择,这次使用来自“reshape2”的meltdcast

library(reshape2)
dcast(
  melt(lapply(mget(ls(pattern='^v\\d+')), as.data.frame), id.vars = "V1"), 
  V1 ~ L1, value.var = "value")
#    V1         v1          v2        v3
# 1   1 -0.6264538  1.51178117        NA
# 2   2  0.1836433  0.38984324        NA
# 3   3 -0.8356286 -0.62124058        NA
# 4   4  1.5952808          NA        NA
# 5   5  0.3295078          NA        NA
# 6   6 -0.8204684 -2.21469989        NA
# 7   7  0.4874291  1.12493092        NA
# 8   8  0.7383247 -0.04493361        NA
# 9   9  0.5757814 -0.01619026        NA
# 10 10 -0.3053884          NA        NA
# 11 11         NA          NA 0.9438362
# 12 12         NA          NA 0.8212212

【讨论】:

    【解决方案3】:

    你可以的

    lst <- mget(ls(pattern='^v\\d+'))
    Un <- sort(unique(unlist(lapply(lst,`[`, ,1 ))))
    cbind(timestamp=Un,sapply(lst, function(x) 
                 ifelse(Un %in% x[,1], x[,2], NA)))
    #    timestamp      v1         v2        v3
    # [1,]    1 -0.21183360 -1.7427876        NA
    # [2,]    2 -1.04159113 -1.3249530        NA
    # [3,]    3 -1.15330756 -0.5479339        NA
    # [4,]    4  0.32153150         NA        NA
    # [5,]    5 -1.50012988         NA        NA
    # [6,]    6 -0.44553326  0.9275789        NA
    # [7,]    7  1.73404543 -0.7167693        NA
    # [8,]    8  0.51129562 -1.7427876        NA
    # [9,]    9  0.09964504 -1.3249530        NA
    # [10,]   10 -0.05789111         NA        NA
    # [11,]   11          NA         NA 0.9623997
    # [12,]   12          NA         NA 1.5458846
    

    数据

    set.seed(25)
    v1 <- matrix(c(seq(1:10), rnorm(10)), nrow=10, ncol=2)
    v2 <- cbind(c(1,2,3,6,7,8,9), rnorm(7))
    v3 <- cbind(11:12, rnorm(2))    
    

    【讨论】:

      【解决方案4】:

      希望对你有帮助

      http://www.inside-r.org/packages/cran/qpcR/docs/cbind.na

      或者下面是一个例子

      库(plyr)

      >> x 
      > [1] 1 2 3 4 5 6 
      
      >> y 
      > [1] 34  5  6 
      

      t(rbind.fill.matrix(matrix(x,nrow=1),matrix(y,nrow=1)))

        [,1] [,2] 
      1    1   34 
      2    2    5 
      3    3    6 
      4    4   NA 
      5    5   NA 
      6    6   NA 
      

      【讨论】:

        【解决方案5】:

        假设你总是有三个向量:

        M <- matrix(NA, 12, 4)
        M[,1]       <- 1:12   # Fill first column
        M[v1[,1],2] <- v1[,2] # Fill second column
        M[v2[,1],3] <- v2[,2] # Fill third column
        M[v3[,1],4] <- v3[,2] # Fill fourth column
        

        这应该很容易推广到任意维度。

        【讨论】:

        • 这是有效的,因为“时间戳”等于行号,但如果“时间戳”不是连续数字,这可能会导致奇怪的东西......如果有的话,这也可能有点耗时,例如,40 个“向量”...
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多