nbren12
nbren12

Reputation: 684

Filling a given dimension inteligently while reshaping array in R

Suppose I have n observations of some field over a 100x100 grid, and that this data is stored as a single vector obs. I would like to reshape this into a 100x100xn array without knowing what n is advance. In matlab I can use

reshape(obs,100,100,[]);

or in python

np.reshape(obs,(100,100,-1))

Is there similar functionality in R or do I have to manually calculate the size of the last index?

Upvotes: 2

Views: 88

Answers (3)

PascalVKooten
PascalVKooten

Reputation: 21453

Try this (I am sure you can adapt it to your further needs):

shaper <- function(obs, a, b) {
 array(obs, dim=c(a, b, length(obs)/a/b))
}
shaper(obs, 100, 100)

If you are not sure whether the size will be correct that you require, you can include a check to see if there are leftovers, something like this:

shaper <- function(obs, a, b) {
  dimension <- length(obs)/a/b 
  if (dimension %% 1 != 0) { 
   stop("not correctly divisible")
  }
  else {
   return(array(obs, dim=c(a, b, dimension)))
  }
}
shaper(obs, 100, 100)

Also added the functionality to give any amount of dimensions as input, and it will try to extend it by 1.

shaper <- function(obs, ...) {
 len.remaining <- length(obs)
 for (i in c(...)) {
   len.remaining <- len.remaining / i
 }
 if (len.remaining %% 1 != 0) { 
  stop("not correctly divisible")
 }
 else {
  return(array(obs, dim=c(..., len.remaining)))
 } 
}

Now it will be possible to use:

obs <- rep(1, 100 * 100 * 5)
> res <- shaper(obs, 100, 100)
> dim(res) 
[1] 100 100 5
> res <- shaper(obs, 10, 10, 100)
> dim(res)
[1] 10 10 100 5

Upvotes: 2

nbren12
nbren12

Reputation: 684

Working off of dualinity's code above I implemented an R function like the np.reshape syntax

npreshape <- function(x,shape) {
    x<- array(x)
    ind <- which(shape ==  -1)
    shape[ind] = prod(dim(x))/prod(shape[-ind])
    return(array(x,shape))
}

Here is how it works in console

> npreshape(1:10,c(-1,5))
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    3    5    7    9
[2,]    2    4    6    8   10

Upvotes: 0

agstudy
agstudy

Reputation: 121578

Does this what do you want?

 dim(obs) <- c(100,100,length(v)/100/100)

For example:

v <- seq(2*2*3)
dim(v) <- c(2,2,length(v)/2/2)

, , 1

     [,1] [,2]
[1,]    1    3
[2,]    2    4

, , 2

     [,1] [,2]
[1,]    5    7
[2,]    6    8

, , 3

     [,1] [,2]
[1,]    9   11
[2,]   10   12

Note that for

  v <- seq(2*2*3+1)

You will get an error :

Error in dim(v) <- c(2, 2, length(v)/2/2) : 
  dims [product 12] do not match the length of object [13]

Upvotes: 2

Related Questions