【问题标题】:R: replacing a sub-array dynamicallyR:动态替换子数组
【发布时间】:2018-05-27 04:01:59
【问题描述】:

我正在处理相当大的多维数组,我非常喜欢使用 abind-package 方式 (abind::asub) 从具有可变维度的数组中动态提取子数组。

但是,我想找到一种有效的方法来执行相反的操作,即用另一个数组动态替换一个子数组。使用'[<-'-function 的基本 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.

一开始用于生成目标的标准子替换函数'[&lt;-' 对我来说已经足够快了,所以我希望能够编写一个快速生成必要参数/下标的包装器(例如 ,,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!

有没有办法动态生成必要的下标参数并将其传递给基本的[&lt;-replacement 函数?或任何其他方式来实现快速动态替换多维子数组的既定目标。

【问题讨论】:

  • 这听起来像是 do.call 的工作。
  • 你可以看到here 一个类似的帖子
  • 谢谢 JDL 和 alexis_laz! do.call 和一个合适的列表(大部分是空元素)似乎是一个非常好的方法。

标签: arrays r multidimensional-array replace


【解决方案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

谢谢!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-22
    • 2020-04-30
    • 2016-12-17
    • 1970-01-01
    • 2022-08-16
    • 2015-01-11
    • 2016-02-08
    • 2020-04-10
    相关资源
    最近更新 更多