Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assign values to a specific dimension of array in R

Tags:

arrays

r

I have a multiple dimension array and try to assign values to a specific dimension. Please see codes below for my current method.

# Create a array and fill with NA
set.seed(1)
dim_arr <- seq(2, 10)
arr <- array(NA, dim = dim_arr)

# Add values to the dimension 2 and fill other dimensions
add_dim <- 2

# Generate value
values <- runif(prod(dim_arr[-add_dim]))
# Assign value to position 1 of dimension 2
arr[,1,,,,,,,] <- values

values <- runif(prod(dim_arr[-add_dim]))
# Assign value to position 2 of dimension 2
arr[,2,,,,,,,] <- values

My problem is that the number of dimension (dim_arr) and changed dimension (add_dim) are not fixed. When parameters dim_arr and add_dim are changed, the code "arr[,1,,,,,,,]" is broken which I have to change it every time.

Is there any generic method to improve my codes?

Please let me know if my question is not clear. Thanks for any suggestions.

like image 871
Bangyou Avatar asked Dec 29 '25 16:12

Bangyou


1 Answers

The correct way to do this will be to a call to do.call specifying the full extent of each dimension other than the one you want (e.g. do.call("[<-", list(arr, 1:x, 1:y, 3, values)). The fun way is to take advantage of the mysterious missing object to generate the empty arguments in x[,,,z,,,].

EDIT: a more boring but simpler approach is included at the end as it turns out a single TRUE as an argument is equivalent to the missing argument.

EDIT2: simplified with Hadley's substitute() approach.

replace_dim <- function(arr, rep.val, dim.to.rep, dim.val) {
  dim.list <- replicate(length(dim(arr)), substitute())
  dim.list[dim.to.rep] <- dim.val
  do.call(`[<-`, c(list(arr), dim.list, list(rep.val)))
}
arr <- array(1:8, dim=rep(2, 3))

replace_dim(arr, 555, 3, 1)  # note this doesn't modify `arr`, so you would have to set `arr` to the return value
# , , 1
#      [,1] [,2]
# [1,]  555  555
# [2,]  555  555
# , , 2
#      [,1] [,2]
# [1,]    5    7
# [2,]    6    8

replace_dim(arr, 555, 2, 1)
# , , 1
#      [,1] [,2]
# [1,]  555    3
# [2,]  555    4
# , , 2
#      [,1] [,2]
# [1,]  555    7
# [2,]  555    8

replace_dim(arr, 555, 1, 1)
# , , 1
#      [,1] [,2]
# [1,]  555  555
# [2,]    2    4
# , , 2
#      [,1] [,2]
# [1,]  555  555
# [2,]    6    8

replace_dim(arr, 555, 1, 2)
# , , 1
#      [,1] [,2]
# [1,]    1    3
# [2,]  555  555
# , , 2
#      [,1] [,2]
# [1,]    5    7
# [2,]  555  555  

Also, here we used 555, but you could have used any vector/object that fits the dimensions you are inserting into.

replace_dim_boring <- function(arr, rep.val, dim.to.rep, dim.val) {
  dim.list <- as.list(rep(T, length(dim(arr))))
  dim.list[dim.to.rep] <- dim.val
  do.call(`[<-`, c(list(arr), dim.list, list(rep.val)))
}
like image 163
BrodieG Avatar answered Dec 31 '25 07:12

BrodieG