【问题标题】:Operation of matrix in R based on dimension namesR中基于维度名称的矩阵运算
【发布时间】:2018-03-05 21:43:21
【问题描述】:

我有一个对称矩阵s 定义为:

s<-matrix(1:25,5)
s[lower.tri(s)] = t(s)[lower.tri(s)]
dimnames(s) <- list(LETTERS[1:5], LETTERS[1:5])
s

   A  B  C  D  E
A  1  6 11 16 21
B  6  7 12 17 22
C 11 12 13 18 23
D 16 17 18 19 24
E 21 22 23 24 25

另外还有一个向量t定义为:

t <- seq(1,10)
names(t) <- c('C_A', 'E_A', 'E_B', 'E_C', 'E_D', 'D_A', 'D_B', 'D_C', 'C_B', 'A_B')

现在我想将t的元素添加到s的上下三角形元素中,这样t的元素名称为'C_A'被添加到@的元素中987654329@,行和列名称分别为“C”和“A”(或“A”和“C”),t 的名称为“E_A”的元素被添加到 s 的元素中,行和'E' 和 'A'(或 'A' 和 'E')等列名。例如,s['A','B'] 和 s['B','A'] 都应该是由 t['A_B'] 添加,对于所有其他非对角元素也是如此。对角线什么也不做。

实现此目的的优雅方法是什么?

【问题讨论】:

标签: r matrix


【解决方案1】:

这不是特别优雅,但是:

s<-matrix(1:25,5)
s[lower.tri(s)] = t(s)[lower.tri(s)]
dimnames(s) <- list(LETTERS[1:5], LETTERS[1:5])

t <- seq(1,10)
names(t) <- c('C_A', 'E_A', 'E_B', 'E_C', 'E_D', 'D_A', 'D_B', 'D_C', 'C_B', 'A_B')

s[t(do.call(cbind, strsplit(names(t), split = "_")))] <-
  s[t(do.call(cbind, strsplit(names(t), split = "_")))] + t
s
#>    A  B  C  D  E
#> A  1 16 11 16 21
#> B  6  7 12 17 22
#> C 12 21 13 18 23
#> D 22 24 26 19 24
#> E 23 25 27 29 25

要添加第 [i,j] 个元素,只需再次调用它,并反转索引位置

s[t(do.call(cbind, strsplit(names(t), split = "_")))[,2:1]] <-
      s[t(do.call(cbind, strsplit(names(t), split = "_")))[,2:1]] + t
s
#>    A  B  C  D  E
#> A  1 16 12 22 23
#> B 16  7 21 24 25
#> C 12 21 13 26 27
#> D 22 24 26 19 29
#> E 23 25 27 29 25

【讨论】:

  • 谢谢! s 中的某些元素似乎没有正确添加?比如s['B', 'A'], s['D', 'A']等。也没有添加上三角部分。
  • s['A','B'] 是 6,应该添加第十个元素,所以它应该是 16,因为结果不是?并且点 ['A', 'D'] 不在 t 中。也许我对您想要的输出感到困惑?
  • 对不起。 s['A','B'] 和 s['B','A'] 都应该由 t['A_B'] 相加,对于所有其他非对角线元素也是如此。我会在 OP 中澄清它。
【解决方案2】:

使用outer创建row/col和col/row索引,然后覆盖s的对应值:

sel1 <- match(names(t), outer(rownames(s),colnames(s), function(x,y) paste(x,y,sep="_")))
sel2 <- match(names(t), outer(rownames(s),colnames(s), function(x,y) paste(y,x,sep="_")))
s[sel1] <- s[sel1]+t
s[sel2] <- s[sel2]+t

#   A  B  C  D  E
#A  1 16 12 22 23
#B 16  7 21 24 25
#C 12 21 13 26 27
#D 22 24 26 19 29
#E 23 25 27 29 25

【讨论】:

    【解决方案3】:

    错误:将修复:您可以将矩阵索引与行和列的字符值的两列矩阵一起使用:

    nt <- strsplit(names(t), "_")
    dnt <- data.frame(n=t, t(data.frame(nt)))
    s[ as.matrix(dnt[-1]) ] <- s[ as.matrix(dnt[-1]) ] + t
    s
    #-----------
       A  B  C  D  E
    A  1 16 11 16 21
    B  6  7 12 17 22
    C 12 21 13 18 23
    D 22 24 26 19 24
    E 23 25 27 29 25
     s[as.matrix(dnt[c(3,2)])] <- s[as.matrix(dnt[c(3,2)])] + t
    s
    #----------
       A  B  C  D  E
    A  1 16 13 28 25
    B 26  7 30 31 28
    C 12 21 13 34 31
    D 22 24 26 19 34
    E 23 25 27 29 25
    

    【讨论】:

    • 我以为我做到了。我错过了您希望在早期版本中添加 t 的事实
    【解决方案4】:
    t1 <- as.list(t)
    p <- for(i in 1 :length(t1))
    {
      nam <-unlist(strsplit(names(t1[i]),"_"))
      s[nam[1],nam[2]]<- t[[i]]
      s[nam[2],nam[1]]<- t[[i]]
    }
    
    > s
       A  B  C  D  E
    A  1 10  1  6  2
    B 10  7  9  7  3
    C  1  9 13  8  4
    D  6  7  8 19  5
    E  2  3  4  5 25
    

    【讨论】:

    • 最后的结果好像不正确?我通过@gfgm 验证了答案。
    猜你喜欢
    • 2014-04-05
    • 2014-05-31
    • 1970-01-01
    • 1970-01-01
    • 2016-03-31
    • 1970-01-01
    • 1970-01-01
    • 2019-11-30
    • 2018-03-28
    相关资源
    最近更新 更多