[R] modify subset of array in list in a function
William Dunlap
wdunlap at tibco.com
Thu Jan 23 18:13:27 CET 2014
> But the last
> part is giving me trouble, since in R calls are by value, not reference,
> so I don't end up modifying the original array in the code below (when
> set_subarray is called):
You can get this effect with R-like syntax by
(a) changing set_subarray to `set_subarray<-`, putting the 'value' argument
at the end and calling it as 'subarray(array,index) <- value' and
(b) having the function return the modified array
Here is an untested version of your function with those changes
`subarray<-` <- function(array, index, value) { # (a) new name and argument list order
## equivalent to array[index, , ...] <- value
if (is.vector(array))
array[index] <- value
else {
rank_ <- length(dim(array))
stopifnot(rank_ >= 1)
do.call("[<-",c(list(array,value,index),rep(TRUE,rank_-1)))
}
array # (b) new return value
}
Bill Dunlap
TIBCO Software
wdunlap tibco.com
> -----Original Message-----
> From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On Behalf
> Of Tamas Papp
> Sent: Thursday, January 23, 2014 3:51 AM
> To: r-help at r-project.org
> Subject: [R] modify subset of array in list in a function
>
> Hi,
>
> I am trying to implement a function that would allow functional
> transformations of posterior simulations (useful in posterior predictive
> checks after MCMC, eg in Stan).
>
> A posterior simulation is a list of vectors and arrays. Usually, one
> uses loops to transform it, but that's error prone. I was thinking of
> ending up with an interface like this (toy example):
>
> --8<---------------cut here---------------start------------->8---
> posterior <- list(a=1:3,b=matrix(4:9,nrow=3))
>
> map_posterior(posterior, function(a,b) {
> list(d=a*sum(b))
> }) # should be equivalent to list(d=posterior$a + rowSums(posterior$b))
> --8<---------------cut here---------------end--------------->8---
>
> I started coding it: I make an arglist for do.call, matching names,
> then deconstruct the value and save it where it belongs. But the last
> part is giving me trouble, since in R calls are by value, not reference,
> so I don't end up modifying the original array in the code below (when
> set_subarray is called):
>
> --8<---------------cut here---------------start------------->8---
> leading_dimension <- function(array) {
> if (is.vector(array))
> length(array)
> else
> dim(array)[1]
> }
>
> common_leading_dimension <- function(array_list) {
> ## if all leading dimensions are the same, return it, otherwise signal an error
> length_ <- length(array_list)
> stopifnot(length_ > 0)
> ld <- leading_dimension(array_list[[1]])
> if (length_ > 1)
> for (i in 2:length_)
> stopifnot(leading_dimension(array_list[[i]])==ld)
> ld
> }
>
> subarray <- function(array, index) {
> ## equivalent to array[index, , ...]
> if (is.vector(array))
> array[index]
> else {
> rank_ <- length(dim(array))
> stopifnot(rank_ >= 1)
> do.call("[",c(list(array,index),rep(TRUE,rank_-1)))
> }
> }
>
> set_subarray <- function(value, array, index) {
> ## equivalent to array[index, , ...] <- value
> if (is.vector(array))
> array[index] <- value
> else {
> rank_ <- length(dim(array))
> stopifnot(rank_ >= 1)
> do.call("[<-",c(list(array,value,index),rep(TRUE,rank_-1)))
> }
> }
>
> map_posterior <- function(posterior,f) {
> names_ <- names(posterior)
> ld <- common_leading_dimension(posterior)
> result <- NULL
> for (index in 1:ld) {
> row_args <- Map(function(name) subarray(posterior[[name]],index),names_)
> names(row_args) <- names_
> row_result <- do.call(f,row_args)
> if (is.null(result)) {
> result <- Map(function(value) {
> dims <- if(is.vector(value)) {
> length_ <- length(value)
> if (length_ == 1)
> NULL
> else
> length_
> } else {
> dim(value)
> }
> array(NA,c(ld,dims))
> },row_result)
> names(result) <- names(row_result)
> }
> Map(function(row_result_name,row_result_value) {
> set_subarray(row_result_value,result[[row_result_name]],index)
> })
> }
> result
> }
> --8<---------------cut here---------------end--------------->8---
>
> Any help or hints on how to do this would be appreciated, including
> alternative approaches of doing/programming the same thing.
>
> Best,
>
> Tamas
>
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
More information about the R-help
mailing list