如何用tidyverse按索引将矩阵转换为tibble/data.frame?
问题
我有一个名为foo的矩阵,想要将其转换为类似bar的长格式data.frame或tibble,同时保留矩阵的索引作为列。请问用tidyverse工具包实现这个需求的简便方法是什么?
示例代码:
z <- c(1,8,6,4,7,3,2,4,7) foo <- matrix(z,3,3) bar <- expand.grid(j=1:3,i=1:3) bar$z <- z foo bar
解决方案
在tidyverse生态里,结合tibble和tidyr的函数就能轻松搞定,这里给你两种常用的简洁写法:
方法1:一步到位转成目标格式
library(tidyverse) foo_tbl <- as_tibble(foo, rownames = "i") %>% pivot_longer(cols = -i, names_to = "j", values_to = "z") %>% # 把列名里的"V"去掉,转成整数索引,和bar格式对齐 mutate(j = as.integer(str_remove(j, "V")), i = as.integer(i)) %>% # 调整列顺序和bar一致 select(j, i, z)
方法2:拆分步骤更清晰
如果觉得上面的步骤太紧凑,也可以拆开来写,逻辑更直观:
foo_tbl <- foo %>% # 先转成data.frame as.data.frame() %>% # 把行索引转成单独的列i rownames_to_column("i") %>% # 把宽格式转成长格式,提取列索引作为j pivot_longer(cols = -i, names_to = "j", values_to = "z") %>% # 把i和j转成整数类型 mutate(across(c(i, j), ~as.integer(str_remove(.x, "V|^$")))) %>% # 调整列顺序匹配bar select(j, i, z)
验证结果
运行完上面的代码后,foo_tbl的结构和内容就和你定义的bar完全一致了,你可以用all.equal(foo_tbl, bar)来验证两者是否等价。如果不需要严格匹配bar的列顺序,还可以去掉最后的select步骤,进一步简化代码。
内容的提问来源于stack exchange,提问作者user111024
相关产品推荐
相关产品推荐

