从 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)
了解它是如何计算的。
Map
将 eg
中的 dim3/dim4 值分配给每个平面。
do.call(rbind, ...)
获取 data.frame
的列表并生成单个帧。它类似于 rbind(out[[1]], out[[2]], out[[3]], ...)
,但以与存储在 out
的元素中的平面数量无关的方式完成。
我有一个最初是 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)
了解它是如何计算的。Map
将eg
中的 dim3/dim4 值分配给每个平面。do.call(rbind, ...)
获取data.frame
的列表并生成单个帧。它类似于rbind(out[[1]], out[[2]], out[[3]], ...)
,但以与存储在out
的元素中的平面数量无关的方式完成。