对一个矩阵列表进行行命名

5
假设我有一个名为 Tables 的矩阵列表,其中包含列名称但不包含行名称。
 Tables <- list(structure(c(0.810145949194718, 0.0792559803788517, 0.189854050805282, 
0.920744019621148), .Dim = c(2L, 2L), .Dimnames = list(NULL, 
    c("e", "prod"))), structure(c(0.949326264941026, 0.24010922539329, 
0.0506737350589744, 0.75989077460671), .Dim = c(2L, 2L), .Dimnames = list(
    NULL, c("prod", "e"))))

我希望行名与列名相同:
rownames(Tables[[1]])<- colnames(Tables[[1]])
rownames(Tables[[2]])<- colnames(Tables[[2]])

我尝试使用lapply但没有成功

lapply(Tables, function(x) rownames(x) <- colnames(x))

我使用了一个 for 循环来完成它

for(i in 1:length(Tables)){
  rownames(Tables[[i]])<- colnames(Tables[[i]])
}

Tables # Expected result
[[1]]
              e      prod
e    0.81014595 0.1898541
prod 0.07925598 0.9207440

[[2]]
          prod          e
prod 0.9493263 0.05067374
e    0.2401092 0.75989077

尽管如此,我想找到一种使用任何*apply或基础中的任何其他函数来避免for循环的方法,但我无法实现这个目标。 我阅读了this,但我无法弄清如何使用其中任何解决方案。 有什么建议吗?

请注意,您提供的Tables对象中的矩阵已经具有匹配的列和行名称。 - Josh O'Brien
这是一个足够简单的操作,我没有看到任何错误或缓慢的地方,可以使用for循环。 - Carl Witthoft
4
我不知道 @Henrik 为什么删除了他的回答,但我同意他的观点:你在 lapply 中的匿名函数需要返回 x,也就是说,lapply(Tables, function(x) {rownames(x) <- colnames(x); x}) - Roland
哦,Roland,你说得完全正确。:D - Jilber Urbina
@Roland,当我意识到原始表格有行名时,我开始怀疑我的答案。不得不创建一个新的矩阵来检查它是否有效。我认为它有效了... - Henrik
显示剩余3条评论
4个回答

7
lapply(Tables, function(x){
  rownames(x) <- colnames(x)
  x
})

# [[1]]
#               e      prod
# e    0.81014595 0.1898541
# prod 0.07925598 0.9207440
# 
# [[2]]
#           prod          e
# prod 0.9493263 0.05067374
# e    0.2401092 0.75989077

5
另一个选择:
for (x in Tables) 
   data.table::setattr(x, "dimnames", list(colnames(x), colnames(x))) 


[[1]]
              e      prod
e    0.81014595 0.1898541
prod 0.07925598 0.9207440

[[2]]
          prod          e
prod 0.9493263 0.05067374
e    0.2401092 0.75989077

但是为什么要使用lapply呢?如果你想要副作用,只需使用for循环即可。 - Roland

4

R已经拥有你所需的一切 :-)

(注:无需翻译)
Tables <- Map(`rownames<-`, Tables, lapply(Tables, colnames))

1
我认为这篇文章值得更多的投票,因为它展示了R语言函数式编程的强大之处,以及将运算符转化为自定义函数的酷炫方式。 - Carl Witthoft

1

Here's one way:

lapply(seq_along(Tables), function(i) {
    rownames(Tables[[i]]) <<- colnames(Tables[[i]])
    return(invisible())
})

...这样写很丑陋 -- 最好使用循环。或者,如果你确实想使用lapply,可以尝试:

Tables <- lapply(Tables, function(x) {
    rownames(x) <- colnames(x)
    return(x)
})

有人之前发布了这个问题,但似乎已经删除了他们的回答。


3
第二个方案是正确的解决方案。第一个方案严重违反了函数式语言的原则,而且与lapply的本意相悖,即lapply应该是一个没有副作用的循环。 - Roland
2
如果您删除第一个解决方案并保留第二个,我会点赞; =)哎呀,我看到@Roland和我同时想到了同样的事情,但我会留下我的评论来帮助说服您第一个解决方案很糟糕! - Josh O'Brien
1
@Adrian 谢谢你的回答 +1,并且请注意 Josh 的评论以获得另一个赞。 - Jilber Urbina
我同意第一个代码非常糟糕、难看且难以阅读。我只是试图编写类似于原问题中的 lapply(Tables, function(x) rownames(x) <- colnames(x)) 的代码。 - Adrian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接