编辑:我已经简化了示例和@jdorbes注释之后的功能。希望这可以改善帖子。
我有一系列的N维数组,我需要沿着它们的第一维“旋转”(例如,在2d矩阵中,在列的第一半和第二半之间相互切换)。 例如,考虑3D情况,我可以将数组定义为:
field <- array(1:32, c(4, 4, 2))
我开发了一个非常基本且与尺寸相关的功能,可以实现目标。当然,也可以使用head
和tail
进行相同的操作,但是我发现这是更快的方法:
rotate.test <- function(field) {
xxx <- field
dims <- length(dim(xxx))
if (dims == 2) { # for x,y data
ll <- length(field[, 1])
field[(ll * 0.5 + 1 ):ll, ] <- xxx[1:(ll * 0.5), ]
field[1:(ll * 0.5), ] <- xxx[(ll * 0.5 + 1):ll, ]
}
if (dims == 3) { # for x,y,t data
ll <- length(field[, 1, 1])
field[(ll * 0.5 + 1 ):ll, , ] <- xxx[1:(ll * 0.5), , ]
field[1:(ll * 0.5), , ] <- xxx[(ll * 0.5 + 1):ll, , ]
}
return(field)
}
结果显示为:
> rotate.test(field)
, , 1
[,1] [,2] [,3] [,4]
[1,] 3 7 11 15
[2,] 4 8 12 16
[3,] 1 5 9 13
[4,] 2 6 10 14
, , 2
[,1] [,2] [,3] [,4]
[1,] 19 23 27 31
[2,] 20 24 28 32
[3,] 17 21 25 29
[4,] 18 22 26 30
这可以进一步推广到N维数据,但是我想您会发现它非常笨拙。
在这篇Select along one of n dimensions in array的帖子之后,我发现可以对其进行概括,向do.call
函数引入非常有用的调用:
array_indexing <- function(field, dim, value, drop = FALSE) {
indices <- rep(list(bquote()), length(dim(field)))
indices[[dim]] <- value
out <- do.call("[",c(list(field), indices, list(drop = drop)))
return(out)
}
然后使用abind
rotate.evo <- function(field) {
require("abind")
xdim <- 1
ll <- dim(field)[xdim]
firstchunk <- array_indexing(field, xdim, (ll * 0.5 + 1):ll)
secondchunk <- array_indexing(field, xdim, 1:(ll * 0.5))
out <- abind(firstchunk, secondchunk, along = 1)
return(out)
}
但是,由于调用了rbenchmark
而不是简单的索引替换,基准测试(用abind
完成)很糟糕。
test replications elapsed relative user.self sys.self
2 rotate.evo(field) 1000 0.547 6.36 0.542 0.005
1 rotate.test(field) 1000 0.086 1.00 0.069 0.016
user.child sys.child
2 0 0
1 0 0
这是我的问题:有没有办法像array_indexing
函数那样概括索引替换?换句话说,是否有任何方法可以快速而可靠地执行此切换,而无需为每个维度编写临时案例?我试图找出的是R中存在的一种方法,用于沿定义的维度概括替换某些数组索引。
我知道这听起来像是一个奇怪的请求,但是如果我可以避免加载额外的程序包,那就太好了。该代码包含在一个在线工具中,该工具应该更轻巧(实际上,我也想摆脱绑定!)
感谢您的任何提示,请询问我的解释是否不完整。 最好, 保罗