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.
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)))
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With