在R中将4维数组转换为2维数据集

5

我想把一个4维数组转化成一个2维数据集。我提供了两种方法的代码,一种使用cbindrbind的暴力方法,另一种使用嵌套的for循环。然而,我认为可能有更好的方法。感谢您提出的任何建议。

R <- 3    # regions
M <- 5    # sites
J <- 2    # samples
T <- 4    # years

# 4-dim example array

y <- array(NA, dim = c(M, J, T, R))

# region 1
y[,1,1,1] =  1; y[,2,1,1] =  2; 
y[,1,2,1] =  3; y[,2,2,1] =  4; 
y[,1,3,1] =  5; y[,2,3,1] =  6;
y[,1,4,1] =  7; y[,2,4,1] =  8;

# region 2
y[,1,1,2] =  9; y[,2,1,2] = 10; 
y[,1,2,2] = 11; y[,2,2,2] = 12; 
y[,1,3,2] = 13; y[,2,3,2] = 14;
y[,1,4,2] = 15; y[,2,4,2] = 16;

# region 3
y[,1,1,3] = 17; y[,2,1,3] = 18; 
y[,1,2,3] = 19; y[,2,2,3] = 20; 
y[,1,3,3] = 21; y[,2,3,3] = 22;
y[,1,4,3] = 23; y[,2,4,3] = 24;

# desired two-dimensional data set

z = read.table(text = "
 1  2  3  4  5  6  7  8
 1  2  3  4  5  6  7  8
 1  2  3  4  5  6  7  8
 1  2  3  4  5  6  7  8
 1  2  3  4  5  6  7  8
 9 10 11 12 13 14 15 16
 9 10 11 12 13 14 15 16
 9 10 11 12 13 14 15 16
 9 10 11 12 13 14 15 16
 9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
17 18 19 20 21 22 23 24
17 18 19 20 21 22 23 24
17 18 19 20 21 22 23 24
17 18 19 20 21 22 23 24
", sep = "", header = FALSE)

# using cbind and rbind to convert 4-dimensional array to 2-dimensional data set

r1 <- cbind(y[,,1,1], y[,,2,1], y[,,3,1], y[,,4,1])
r2 <- cbind(y[,,1,2], y[,,2,2], y[,,3,2], y[,,4,2])
r3 <- cbind(y[,,1,3], y[,,2,3], y[,,3,3], y[,,4,3])

my.data <- rbind(r1,r2,r3)
my.data

# using nested for-loops to convert 4-dimensional array to 2-dimensional data set

m2 <- matrix(NA, nrow = M*R, ncol= J*T)

for(i in 1:R) {
for(j in 1:T) {

m2[(M*(i-1) + (1:M)), (J*(j-1) + (1:J))] = y[,,j,i]

}
}

m2

# basis for nested for-loops above

m3 <- matrix(NA, nrow = M*R, ncol= J*T)

m3[(M*0 + (1:M)), (J*0 + (1:J))] = y[,,1,1]
m3[(M*0 + (1:M)), (J*1 + (1:J))] = y[,,2,1]
m3[(M*0 + (1:M)), (J*2 + (1:J))] = y[,,3,1]
m3[(M*0 + (1:M)), (J*3 + (1:J))] = y[,,4,1]

m3[(M*1 + (1:M)), (J*0 + (1:J))] = y[,,1,2]
m3[(M*1 + (1:M)), (J*1 + (1:J))] = y[,,2,2]
m3[(M*1 + (1:M)), (J*2 + (1:J))] = y[,,3,2]
m3[(M*1 + (1:M)), (J*3 + (1:J))] = y[,,4,2]

m3[(M*2 + (1:M)), (J*0 + (1:J))] = y[,,1,3]
m3[(M*2 + (1:M)), (J*1 + (1:J))] = y[,,2,3]
m3[(M*2 + (1:M)), (J*2 + (1:J))] = y[,,3,3]
m3[(M*2 + (1:M)), (J*3 + (1:J))] = y[,,4,3]

m3
2个回答

9

经过几次尝试,就成功了:

matrix(aperm(y,c(1,4,2,3)),15)

或更普遍地说
matrix(aperm(y,c(1,4,2,3)),prod(dim(y)[c(1,4)]))

1
如果有人来这里寻找关于折叠到大于dimension=2的数组的类似问题,使用array()而不是matrix(),并使用dim()参数指定您想要的维度。以下代码也适用于上面的问题:
array(aperm(y,c(1,4,2,3)), dim=c(15,8))

如果您想要输出为3D数组,只需在dim()中增加一个额外的值即可轻松修改此内容。aperm()可能对您的特定情况不是必需的,但您应始终检查折叠的数组是否按照您所需的顺序,并相应地使用aperm()。

以上方法会丢失维度名称。应该添加 ... ,dimnames=list(new_dimname, dimname(y)[[2]],dimname(y)[[3]]) ),其中对于 new_dimname,您必须从原始维度名称中选择一个或它们的组合来创建新名称,例如:rep(dimname(y)[[4]],each=dim(y)[1]) - Shajar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接