Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function for resizing matrices in R

Tags:

r

matrix

I was wondering if there was a function that scales down matrices in R statistical software exactly like with image resizing. The function imresize() in MATLAB is exactly what I'm looking for (I believe it takes the average of the surrounding points, but I am not sure of this), but I am wondering if there is an R equivalent for this function.

This question has been posted before on this forum, but with reference to MATLAB, not R: Matlab "Scale Down" a Vector with Averages The post starting with "Any reason why you can't use the imresize() function?" is exactly what I am looking for, but in R, not MATLAB.

Say I have a latitude-longitude grid of temperatures around the world, and let's say this is represented by a 64*128 matrix of temperatures. Now let's say I would like to have the same data contained in a new matrix, but I would like to rescale my grid to make it a 71*114 matrix of temperatures around the world. A function that would allow me to do so is what I'm looking for (again, the imresize() function, but in R, not MATLAB)

Thank you. Steve

like image 638
user1469730 Avatar asked Jun 20 '12 15:06

user1469730


People also ask

How do I resize a matrix in R?

Use resample() to resize matrices.

Can a matrix be resized?

Resizing and Reshaping Matrices :: Data Structures (Programming) You can expand the size of any existing matrix as long as doing so does not give the resulting matrix an irregular shape. (See Keeping Matrices Rectangular).

What is the function of matrix in R?

Matrices are the two-dimensional data structures in R that allow us to store the data into the form of rows and columns and have a dedicated function named matrix() that allows us to create them in the R environment.

How do I change a matrix element in R?

How to modify a matrix in R? We modify the R matrix by using the various indexing techniques along with the assignment operator. We can add a row or column by storing the new row/column in a vector and using the rbind() or cbind() functions to combine them with the matrix. Transposing a matrix is very easy in R.


2 Answers

One way to do this is by using the function resample(), from the raster package.

I'll first show how you could use it to rescale your grid, and then give an easier-to-inspect example of its application to smaller raster objects

Use resample() to resize matrices

library(raster)
m <- matrix(seq_len(68*128), nrow=68, ncol=128, byrow=TRUE)

## Convert matrix to a raster with geographical coordinates
r <- raster(m)
extent(r) <- extent(c(-180, 180, -90, 90))

## Create a raster with the desired dimensions, and resample into it
s <- raster(nrow=71, ncol=114)
s <- resample(r,s)

## Convert resampled raster back to a matrix
m2 <- as.matrix(s)

Visually confirm that resample() does what you'd like:

library(raster)
## Original data (4x4)
rr <- raster(ncol=4, nrow=4)
rr[] <- 1:16
## Resize to 5x5
ss <- raster(ncol=5,  nrow=5)
ss <- resample(rr, ss)
## Resize to 3x3
tt <- raster(ncol=3, nrow=3)
tt <- resample(rr, tt)
## Plot for comparison
par(mfcol=c(2,2))
plot(rr, main="original data")
plot(ss, main="resampled to 5-by-5")
plot(tt, main="resampled to 3-by-3")

enter image description here

like image 196
Josh O'Brien Avatar answered Oct 04 '22 02:10

Josh O'Brien


The answer posted by Josh O'Brien is OK and it helped me (for starting point), but this approach was too slow since I had huge list of data. The method below is good alternative. It uses fields and works much faster.

Functions

rescale <- function(x, newrange=range(x)){
  xrange <- range(x)
  mfac <- (newrange[2]-newrange[1])/(xrange[2]-xrange[1])
  newrange[1]+(x-xrange[1])*mfac
}

ResizeMat <- function(mat, ndim=dim(mat)){
  if(!require(fields)) stop("`fields` required.")

  # input object
  odim <- dim(mat)
  obj <- list(x= 1:odim[1], y=1:odim[2], z= mat)

  # output object
  ans <- matrix(NA, nrow=ndim[1], ncol=ndim[2])
  ndim <- dim(ans)

  # rescaling
  ncord <- as.matrix(expand.grid(seq_len(ndim[1]), seq_len(ndim[2])))
  loc <- ncord
  loc[,1] = rescale(ncord[,1], c(1,odim[1]))
  loc[,2] = rescale(ncord[,2], c(1,odim[2]))

  # interpolation
  ans[ncord] <- interp.surface(obj, loc)

  ans
}

Lets look how it works

## Original data (4x4)
rr <- matrix(1:16, ncol=4, nrow=4)
ss <- ResizeMat(rr, c(5,5)) 
tt <- ResizeMat(rr, c(3,3)) 

## Plot for comparison
par(mfcol=c(2,2), mar=c(1,1,2,1))
image(rr, main="original data", axes=FALSE)
image(ss, main="resampled to 5-by-5", axes=FALSE)
image(tt, main="resampled to 3-by-3", axes=FALSE)

Resized matrix

like image 38
Vyga Avatar answered Oct 04 '22 04:10

Vyga