如何基于行名和列名的比较来构建方阵

时间:2016-07-05 11:33:57

标签: r matrix

矩阵中的列和行的名称与组有关,这些组与其他组具有不同的关系。我想创建一个矩阵,其中的值基于行名和列名以及相应的关系。

我已经创建了一种效率低下的方法,这对于一个小的3 * 3矩阵是可以的,但对大型矩阵来说是不实用的。

我的示例数据如下:

tom <- data.frame("w"=c(7,1,2),"x"=c(2,4,4),"y"=c(12,4,8))
row.names(tom) <- colnames(tom)

same <- data.frame("trait"=c("w","x","y"),
                   "group"=c(1,2,2),
                   "own_group_relationship"=c(0.86,0.55,0.55))

diff <- data.frame("trait"=c("w","x","y"),
                    "diff_group_relationship"=c(0.23,0.23,0.23))

我的陈述是这样的:

a1 <- if ( row.names(tom[c(1),]) == colnames(tom[c(1)]) ) {
  merge(data.frame("trait" = row.names(tom[c(1),])),same)[1,3]
} else {
  merge(data.frame("trait" = row.names(tom[c(1),])),diff)[1,2]
}

目前这适用于一个元素。我不得不多次重复此代码8次,更改相应的行名称以获得9个值(a1到a9)。

a2 <- if ( row.names(tom[c(1),]) == colnames(tom[c(2)]) ) {merge(data.frame("trait" = row.names(tom[c(1),])),same)[1,3]} else {merge(data.frame("trait" = row.names(tom[c(1),])),diff)[1,2]}   
a3 <- if ( row.names(tom[c(1),]) == colnames(tom[c(3)]) ) {merge(data.frame("trait" = row.names(tom[c(1),])),same)[1,3]} else {merge(data.frame("trait" = row.names(tom[c(1),])),diff)[1,2]}   
a4 <- if ( row.names(tom[c(2),]) == colnames(tom[c(1)]) ) {merge(data.frame("trait" = row.names(tom[c(1),])),same)[1,3]} else {merge(data.frame("trait" = row.names(tom[c(1),])),diff)[1,2]}   
a5 <- if ( row.names(tom[c(2),]) == colnames(tom[c(2)]) ) {merge(data.frame("trait" = row.names(tom[c(1),])),same)[1,3]} else {merge(data.frame("trait" = row.names(tom[c(1),])),diff)[1,2]}   
a6 <- if ( row.names(tom[c(2),]) == colnames(tom[c(3)]) ) {merge(data.frame("trait" = row.names(tom[c(1),])),same)[1,3]} else {merge(data.frame("trait" = row.names(tom[c(1),])),diff)[1,2]}   
a7 <- if ( row.names(tom[c(3),]) == colnames(tom[c(1)]) ) {merge(data.frame("trait" = row.names(tom[c(1),])),same)[1,3]} else {merge(data.frame("trait" = row.names(tom[c(1),])),diff)[1,2]}   
a8 <- if ( row.names(tom[c(3),]) == colnames(tom[c(2)]) ) {merge(data.frame("trait" = row.names(tom[c(1),])),same)[1,3]} else {merge(data.frame("trait" = row.names(tom[c(1),])),diff)[1,2]}   
a9 <- if ( row.names(tom[c(3),]) == colnames(tom[c(3)]) ) {merge(data.frame("trait" = row.names(tom[c(1),])),same)[1,3]} else {merge(data.frame("trait" = row.names(tom[c(1),])),diff)[1,2]}   

这9个值很容易转换为3 * 3矩阵,但必须有更优雅的解决方案。

vec <- c(a1,a2,a3,a4,a5,a6,a7,a8,a9)
mtrx <- matrix(vec, nrow=3, ncol=3)
mtrx # the resulting matrix of group inter group relationships
     [,1] [,2] [,3]
[1,] 0.86 0.23 0.23
[2,] 0.23 0.86 0.23
[3,] 0.23 0.23 0.86

1 个答案:

答案 0 :(得分:0)

以下是使用outermatch的解决方案:

outer(rownames(tom), colnames(tom),
      FUN=function(x, y) {
                          (x==y) * same$own_group_relationship[match(x, same$trait)] +
                          (x!=y) * diff$diff_group_relationship[match(x, diff$trait)]
      })

返回

     [,1] [,2] [,3]
[1,] 0.86 0.23 0.23
[2,] 0.23 0.55 0.23
[3,] 0.23 0.23 0.55

内部函数会生成一个向量,该向量将根据行名称和列名称是否匹配来提取正确的值。 outer函数返回正确的位置和尺寸。