如何根据行名和列名的比较构建方阵
Posted
技术标签:
【中文标题】如何根据行名和列名的比较构建方阵【英文标题】:How to build a square matrix based on a comparison of row and column names 【发布时间】:2016-11-07 05:31:34 【问题描述】:我的矩阵中的列和行的名称与组相关,这些组与其他组具有不同的关系。我想创建一个矩阵,其中的值基于行名和列名以及对应关系。
我已经创建了一种低效的方法来执行此操作,这对于小型 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
【问题讨论】:
你不能用vec <- matrix(NA, 3, 3); diag(vec) <- "condition A"; vec[row(vec) != col(vec)] <- "condition B"
之类的东西吗?类似于this question
【参考方案1】:
这是使用outer
和match
的解决方案:
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
函数返回正确的位置和尺寸。
【讨论】:
以上是关于如何根据行名和列名的比较构建方阵的主要内容,如果未能解决你的问题,请参考以下文章