从 4d mat-lab 数组到 R 中的 2d 矩阵或数据框

from 4d mat-lab array to a 2d matrix or data frame in R

我有一个最初是 Matlab .mat 文件的数据集。当我将它导入 R 时,

列表中包含 .mat 文件内容的元素之一似乎是一个多维数组(准确地说是 4d。

看起来像 num[1:41, 1:2400,1:60, 1:6]。我知道这与在 2400 次试验中变化的 41 种特征有关,对于 60 个人中的每一个人来说,就是在每次试验中做出 6 个选择中的一个。

由此我真正想要的只是一个二维矩阵或数据框,其中我可以有 41 列用于特征,一列用于试验,一列用于人员 ID,一列用于存储他们所做的选择, 在那个特定的试验中。

所以基本上每一行都会显示所有 41 个特征的值、人员 ID、试验 ID 和他们的选择。最终,我需要能够在一个文件(如 csv 或 txt)中共享它。

有没有有效的方法来做到这一点?到目前为止,我的解决方案似乎真的很复杂,需要很多循环和 if 语句。 非常感谢

示例数据 ary,假设它在某种程度上代表了您的较大矩阵。

ary <- array(seq(prod(c(4,10,3,2))), dim = c(4,10,3,2))
ary
# , , 1, 1
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,]    1    5    9   13   17   21   25   29   33    37
# [2,]    2    6   10   14   18   22   26   30   34    38
# [3,]    3    7   11   15   19   23   27   31   35    39
# [4,]    4    8   12   16   20   24   28   32   36    40
# , , 2, 1
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,]   41   45   49   53   57   61   65   69   73    77
# [2,]   42   46   50   54   58   62   66   70   74    78
# [3,]   43   47   51   55   59   63   67   71   75    79
# [4,]   44   48   52   56   60   64   68   72   76    80
# , , 3, 1
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,]   81   85   89   93   97  101  105  109  113   117
# [2,]   82   86   90   94   98  102  106  110  114   118
# [3,]   83   87   91   95   99  103  107  111  115   119
# [4,]   84   88   92   96  100  104  108  112  116   120
# , , 1, 2
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,]  121  125  129  133  137  141  145  149  153   157
# [2,]  122  126  130  134  138  142  146  150  154   158
# [3,]  123  127  131  135  139  143  147  151  155   159
# [4,]  124  128  132  136  140  144  148  152  156   160
# , , 2, 2
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,]  161  165  169  173  177  181  185  189  193   197
# [2,]  162  166  170  174  178  182  186  190  194   198
# [3,]  163  167  171  175  179  183  187  191  195   199
# [4,]  164  168  172  176  180  184  188  192  196   200
# , , 3, 2
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,]  201  205  209  213  217  221  225  229  233   237
# [2,]  202  206  210  214  218  222  226  230  234   238
# [3,]  203  207  211  215  219  223  227  231  235   239
# [4,]  204  208  212  216  220  224  228  232  236   240

一个three-step转换过程:

tmp <- apply(ary, 3:4, function(z) as.data.frame(t(z)), simplify = FALSE)
eg <- do.call(expand.grid, lapply(dim(tmp), seq))
out <- do.call(rbind, Map(function(x, d3, d4) transform(x, dim3=d3, dim4=d4), c(tmp), eg[[1]], eg[[2]]))
dim(out)
# [1] 60  6
head(out)
#   V1 V2 V3 V4 dim3 dim4
# 1  1  2  3  4    1    1
# 2  5  6  7  8    1    1
# 3  9 10 11 12    1    1
# 4 13 14 15 16    1    1
# 5 17 18 19 20    1    1
# 6 21 22 23 24    1    1

详情:

  • apply(ary, 3:4, ...) 将在 4d 数组的每个“平面”上应用一个函数。 3:4 表示第 3 维和第 4 维,前两个维度(分别为行和列)保持不变。在匿名函数的单个调用中,z 是一个二维数组,例如 ary[,,1,1]t 将其转置为 4 列宽,以便您可以在列维度中拥有您的特征。

  • eg只是一种对第3维和第4维进行编号的机制,以便我们可以记录每个位面的来源。这个 returns 帧包含 1:dim(ary)[3]1:dim(ary)[4] 的所有组合,并且与我们在 c(tmp) 时得到的顺序相同,保留编号的平面。查看 head(eg) 了解它是如何计算的。

  • Mapeg 中的 dim3/dim4 值分配给每个平面。

  • do.call(rbind, ...) 获取 data.frame 的列表并生成单个帧。它类似于 rbind(out[[1]], out[[2]], out[[3]], ...),但以与存储在 out 的元素中的平面数量无关的方式完成。