我正在使用相当大的多维数组,我非常喜欢abind-package方式(abind::asub
),用于从具有可变维度的数组中动态提取子数组。
但是,我想找到一种有效的方法来进行相反的操作,即用另一个数组动态替换子数组。使用带有'[<-'
- 函数的下标的基本R方式足够快
library(abind) # just to show the wanted dynamical indexing
library(microbenchmark) # speed is essential
array.goal<-array.test<-array.original<-array(rnorm(100000),dim=c(10,10,10,10,10))
array.replacement<-array(1,dim=c(10,10,5,10,10))
microbenchmark(array.goal[,,3:7,,]<-array.replacement) # mean 507.9323 microseconds
但它不是动态的 - 我希望能够使用变量设置目标维度,而不是记下固定数量的逗号。与asub用于提取的样式相同:
# the variables to control the replacement location:
dims<-3
idx<-list(3:7)
# i.e. want to be able to use the same kind of notation that abind::asub
# uses for extracting the sub arrays, as in:
identical(asub(array.goal,dims=dims,idx=idx),array.replacement)
以下通过生成子阵列索引矩阵来实现,但它对我来说太慢了:
findsubi<-function(x,idx,dims){
dim.x<-dim(x)
dim.length<-length(dim.x)
stopifnot(all(dims>=0) & all(dims<=dim.length),class(idx)=="list")
stopifnot(dim.x[dims]>=lapply(idx,max))
allowed<-lapply(dim.x,FUN=function(x){1:x})
allowed[dims]<-idx
index.space<-as.matrix(expand.grid(allowed))
return(index.space)
}
# slooower: mean 4.259752 milliseconds!
microbenchmark(array.test[findsubi(array.test,dims=dims,idx=idx)]<-array.replacement)
identical(array.test,array.goal) # i know they are.
开始时用于生成目标的标准子替换函数'[<-'
对我来说足够快,所以我希望能够编写一个快速生成必要参数/下标的包装器(用于例如,3:7 ,,)为此,避免必须创建定义所需子阵列的单个索引的向量
所以本质上我希望有一个动态abind::asub
样式动态索引的包装器
# let's go back to square one:
array.test<-array.original
asubassi<-function(x,dims,idx,y){
# steps to generate ",,3:7,,"
#argum<-something.to.generate.them(x,dims,idx)
# i'd like to be able to efficiently generate the subscripts dynamically,
# but I don't know how
# you can't just generate a string and use that:
# argum<-',,3:7,,' the line '[<-'(x,argum,y) would fail
'[<-'(x,,,3:7,,,y) # now just an example with a fixed subarray
}
希望它仍然足够快
# mean 620.7229 microseconds
microbenchmark(array.test<-
asubassi(x=array.test,dims=dims,idx=idx,y=array.replacement))
identical(array.test,array.goal) # the truth is out there!
有没有办法动态生成并将必要的下标参数传递给基本[<-
替换函数?或任何其他方式来实现快速动态替换多维子阵列的既定目标。
答案 0 :(得分:1)
感谢@JDL和@alexis_laz的帮助。解决方案是首先动态生成do.call
subarray.argument<-function(x,dims,idx){
dim.x<-dim(x)
dim.length<-length(dim.x)
stopifnot(all(dims>=0) & all(dims<=dim.length),class(idx)=="list")
stopifnot(dim.x[dims]>=lapply(idx,max))
# first a suitable empty list
argument<-rep(list(bquote()),dim.length)
argument[dims]<-idx # insert the wanted dimension slices
return(argument)
}
asubassi<-function(x,dims,idx,y){
argum<-c(alist(x),subarray.argument(x,dims,idx),alist(y))
do.call('[<-',argum)
}
速度足够好:
# mean 773.6759 microseconds
microbenchmark(array.test<-
asubassi(x=array.test,dims=dims,idx=idx,y=array.replacement))
identical(array.test,array.goal) # yep
谢谢!