R语言 将2D矩阵转换为3D数组

yizd12fk  于 2023-04-03  发布在  其他
关注(0)|答案(4)|浏览(201)

我有一个2D矩阵,我想转换成一个3D数组,但我没有得到正确的转换。
我的目标是让它工作,这样,不管我有多少第三维的水平,它都将递归地工作。
以下是数据:

dfs <- (structure(c(-0.046, 0.676, -0.698, -0.047, 0.719, -0.646, -0.044, 
                             0.706, -0.667, 0.046, 0.769, -0.605, 0.047, 0.813, -0.551, 0.044, 
                             0.795, -0.578), dim = c(9L, 2L), dimnames = list(c("snatch:(Intercept)", 
                                                                                "snatch:weight", "snatch:age", "clean:(Intercept)", "clean:weight", 
                                                                                "clean:age", "total:(Intercept)", "total:weight", "total:age"
                             ), c("2.5 %", "97.5 %"))))

我要找的是这样的东西

$a
             X2.5%  X97.5%
(Intercept) -0.046   0.046
weight       0.676   0.769
age         -0.698  -0.605

$b
             X2.5%  X97.5%
(Intercept)  -0.047   0.047
weight        0.719   0.813
age          -0.646  -0.551

$c
             X2.5%  X97.5%
(Intercept)  -0.044   0.044
weight        0.706   0.795
age          -0.667  -0.578

我的剧本和我目前所做的

rnames <- c("(Intercept)", "snatch", "age")
cnames <- colnames(dfs); cnames
lnames <- c("a", "b", "c"); lnames

array(
  data = matrix(data = type.convert(gsub("^[^:]+:\\s*", "", dfs), as.is=TRUE),
                nrow=nrow(dfs), ncol=ncol(dfs)),
  dim = c(nrow(dfs)/length(lnames), length(cnames), length(lnames)),
  dimnames = list(rows=rnames,
                  column=cnames,
                  level=lnames)) %>%
  apply(., 2, data.frame)
jxct1oxe

jxct1oxe1#

你可以尝试split.data.frame,例如,

> split.data.frame(dfs, gsub(":.*", "", row.names(dfs)))
$clean
                   2.5 % 97.5 %
clean:(Intercept) -0.047  0.047
clean:weight       0.719  0.813
clean:age         -0.646 -0.551

$snatch
                    2.5 % 97.5 %
snatch:(Intercept) -0.046  0.046
snatch:weight       0.676  0.769
snatch:age         -0.698 -0.605

$total
                   2.5 % 97.5 %
total:(Intercept) -0.044  0.044
total:weight       0.706  0.795
total:age         -0.667 -0.578
rks48beu

rks48beu2#

我们可以t转置2D矩阵(或者在您的情况下是数据.frame),制作一个array,其中包含维度、列数、唯一前缀数和唯一后缀数(在本例中为c(2, 3, 3)),然后使用aperm转置数组。

aperm(array(t(dfs), c(2, 3, 3)), c(2, 1, 3)) 
# , , 1
# 
#        [,1]   [,2]
# [1,] -0.046  0.046
# [2,]  0.676  0.769
# [3,] -0.698 -0.605
# 
# , , 2
# 
#        [,1]   [,2]
# [1,] -0.047  0.047
# [2,]  0.719  0.813
# [3,] -0.646 -0.551
# 
# , , 3
# 
#        [,1]   [,2]
# [1,] -0.044  0.044
# [2,]  0.706  0.795
# [3,] -0.667 -0.578

为了不使用硬编码,我们可以使用dimnames来获取维度的值以及结果数组的dimnames

f <- \(x) {
  dn <- dimnames(x)
  dn2 <- c(asplit(apply(do.call(rbind, strsplit(dn[[1]], ':')), 2, unique), 2), dn[2])
  aperm(array(data=t(x), dim=c(ncol(x), length(dn2[[2]]), length(dn2[[1]])), dimnames=dn2[c(3, 2, 1)]), c(2, 1, 3)) 
}

f(dfs)
# , , snatch
# 
#              2.5 % 97.5 %
# (Intercept) -0.046  0.046
# weight       0.676  0.769
# age         -0.698 -0.605
# 
# , , clean
# 
#              2.5 % 97.5 %
# (Intercept) -0.047  0.047
# weight       0.719  0.813
# age         -0.646 -0.551
# 
# , , total
# 
#              2.5 % 97.5 %
# (Intercept) -0.044  0.044
# weight       0.706  0.795
# age         -0.667 -0.578
  • 数据:*
dfs <- structure(c(-0.046, 0.676, -0.698, -0.047, 0.719, -0.646, -0.044, 
0.706, -0.667, 0.046, 0.769, -0.605, 0.047, 0.813, -0.551, 0.044, 
0.795, -0.578), dim = c(9L, 2L), dimnames = list(c("snatch:(Intercept)", 
"snatch:weight", "snatch:age", "clean:(Intercept)", "clean:weight", 
"clean:age", "total:(Intercept)", "total:weight", "total:age"
), c("2.5 %", "97.5 %")))
oug3syen

oug3syen3#

我知道这一个是冗长的,老实说,jay.sf和ThomasIsCoding的两个答案肯定更好,但找到一个tidyverse方法很有趣,我发现了abind()函数:

library(tidyverse)
library(abind)

dfs %>%
  as.data.frame() %>% 
  rownames_to_column("names") %>% 
  separate(names, into = c("group", "names"), extra = "drop") %>% 
  group_split(group) %>% 
  purrr::set_names(purrr::map_chr(., ~.$group[1])) %>% 
  map(~ select(.x, -group)) %>% 
  abind(., along = 3)
, , clean

     names       2.5 %    97.5 %  
[1,] "Intercept" "-0.047" " 0.047"
[2,] "weight"    " 0.719" " 0.813"
[3,] "age"       "-0.646" "-0.551"

, , snatch

     names       2.5 %    97.5 %  
[1,] "Intercept" "-0.046" " 0.046"
[2,] "weight"    " 0.676" " 0.769"
[3,] "age"       "-0.698" "-0.605"

, , total

     names       2.5 %    97.5 %  
[1,] "Intercept" "-0.044" " 0.044"
[2,] "weight"    " 0.706" " 0.795"
[3,] "age"       "-0.667" "-0.578"
kcrjzv8t

kcrjzv8t4#

这是你想要的代码:

a <- array(dfs, dim = c(3, 2, 3),
           dimnames = list(gsub(".*:", "", rownames(dfs))[1:3] , 
                           colnames(dfs)))

a <- setNames(lapply(1:3, function(i) a[,,i]), c("a", "b", "c"))

和输出:

> a
$a
             2.5 % 97.5 %
(Intercept) -0.046 -0.047
weight       0.676  0.719
age         -0.698 -0.646

$b
             2.5 % 97.5 %
(Intercept) -0.044  0.046
weight       0.706  0.769
age         -0.667 -0.605

$c
             2.5 % 97.5 %
(Intercept)  0.047  0.044
weight       0.813  0.795
age         -0.551 -0.578

classa是list

相关问题