如何用purrr::map2将嵌套列表行名转移至另一嵌套列表的矩阵
问题解决:为嵌套列表中的矩阵设置行名
问题原因
你的代码核心问题在于:rownames(so) <- cs 这个赋值语句的返回值是右侧的cs(行名字符向量),而非修改后的矩阵。当你用map2时,内部函数默认返回这条语句的结果,导致最终生成的l3里全是行名字符向量,而非带行名的矩阵。
而用walk2/modify2时未生效,是因为没有显式返回修改后的矩阵,且R的值传递特性导致函数内修改的只是矩阵副本,不会影响原列表。
解决方案
方案1:修正嵌套map2,显式返回修改后的矩阵
在内部函数中完成行名赋值后,必须返回修改后的矩阵:
library(tidyverse) mat <- matrix(1:225, nrow = 15) colnames(mat) <- LETTERS[1:15] rnames <- paste("This is name", 1:15) l1 <- list( "sub1" = list("a1" = mat, "a2" = mat, "a3" = mat), "sub2" = list("a1" = mat, "a2" = mat, "a3" = mat) ) l2 <- list( "sub1" = list("a1" = rnames, "a2" = rnames, "a3" = rnames), "sub2" = list("a1" = rnames, "a2" = rnames, "a3" = rnames) ) # 修正后的代码 l3 <- map2(l1, l2, function(sol, csl) { map2(sol, csl, function(so, cs) { rownames(so) <- cs so # 关键:返回修改后的矩阵 }) }) # 验证结果 str(l3[[1]][[1]]) #> int [1:15, 1:15] 1 2 3 4 5 6 7 8 9 10 ... #> - attr(*, "dimnames")=List of 2 #> ..$ : chr [1:15] "This is name 1" "This is name 2" ... #> ..$ : chr [1:15] "A" "B" "C" "D" ...
方案2:用modify2更贴合需求
modify2的设计目标就是修改.x的元素并返回修改后的.x,写法更简洁:
l3 <- modify2(l1, l2, function(sol, csl) { modify2(sol, csl, function(so, cs) { rownames(so) <- cs so }) })
方案3:用R 4.1+的箭头函数简化代码
如果你的R版本在4.1及以上,可以用箭头函数进一步缩短代码:
l3 <- map2(l1, l2, ~ map2(.x, .y, \(m, rn) {rownames(m) <- rn; m}))
内容的提问来源于stack exchange,提问作者zionlion
相关产品推荐
相关产品推荐

