Reputation: 9816
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.
Upvotes: 3
Views: 1144
Reputation: 52637
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)))
}
Upvotes: 3