在R中用于调整矩阵大小的函数

9
我想知道在R统计软件中是否有一个函数,能够像调整图片大小一样缩小矩阵。MATLAB中的imresize()函数正是我要找的(我认为它取周围点的平均值,但我不确定),但我想知道是否有与该函数等效的R函数。
这个问题曾经在这个论坛上发布过,但是与MATLAB有关,而不是R: Matlab "Scale Down" a Vector with Averages 以“为什么不能使用imresize()函数?”开头的帖子正是我要找的,但是是关于R的,而不是MATLAB。
假设我有一个全球温度的纬度-经度网格,并且让我们假设这是由一个64*128的温度矩阵来表示的。现在让我们假设我想要在包含全球温度的新矩阵中具有相同的数据,但我想要重新调整我的网格,使其成为一个71*114的温度矩阵。我想要寻找的是一个可以实现这一点的函数(再次强调,是R版本的imresize()函数,而非MATLAB)。
谢谢。 Steve

这个问题看起来和 https://dev59.com/dGTWa4cB1Zd3GeqPEIn1 一模一样。 - Andrie
许多 R 图像处理包都有一个“调整大小”类似的功能,通常用于缩放。根据您想要折叠值的方式(平均值或样条等),也不难自己编写此功能。那么:您想要什么?网格中的平均温度还是最坏情况(例如最高温度)等? - Carl Witthoft
@CarlWitthoft 你有想到特定的 package::function 吗?我会很高兴,如果你能提供任何提示的话。谢谢。 - Josh O'Brien
@JoshO'Brien 我可能想到的是aggregate,也在raster包中。(还有disaggregate)。如果有人感兴趣,我写了这些工具的复杂版本来处理E-M波前传播。 - Carl Witthoft
我突然想到,太晚了 :-(,在一般情况下,最好使用基于核的卷积方法来处理这个问题。 - Carl Witthoft
2个回答

12

一种实现方式是使用raster包中的resample()函数。

首先我将展示如何使用它来重新缩放网格,然后给出一个更易于检查的示例来说明其在较小的栅格对象上的应用。

使用resample()调整矩阵大小

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)

通过视觉确认 resample() 是否符合你的需求:

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")

输入图像描述


6

Josh O'Brien的答案可以作为一个起点,并且有所帮助,但是当我需要处理大量数据时,这种方法过于缓慢。下面的方法是一种很好的替代方案。它使用fields,执行速度更快。

函数

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
}

让我们看看它是如何工作的

## 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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接