从 akima::interp() 矩阵获取函数 [英] Obtain function from akima::interp() matrix

查看:30
本文介绍了从 akima::interp() 矩阵获取函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 interp 函数(Akima 包),可以绘制与数据集的二元插值相对应的表面,参见下面的示例(来自 interp 文档):

Using the interp function (Akima package), it is possible to draw the surface corresponding to the bivariate interpolation of a data set, see example below (from interp documentation):

library(rgl)
data(akima)
# data visualisation
rgl.spheres(akima$x,akima$z , akima$y,0.5,color="red")
rgl.bbox()
# bivariate linear interpolation
# interp:
akima.li <- interp(akima$x, akima$y, akima$z, 
                   xo=seq(min(akima$x), max(akima$x), length = 100),
                   yo=seq(min(akima$y), max(akima$y), length = 100))
# interp surface:
rgl.surface(akima.li$x,akima.li$y,akima.li$z,color="green",alpha=c(0.5))

然而,输出只是一个描述一组点的列表,而不是一个通用的函数.

However, the output is only a list describing a set of points, not a general function.

问题: 有没有什么方法可以得到与之前得到的曲面相匹配的函数 z = f(x,y) ?我知道它使用 interp(akima$x, akima$y, akima$z, xo=A, yo=B) 工作,但速度很慢.

Question: is there any method to obtain a function z = f(x,y) that matches the previously obtained surface ? I know that it works using interp(akima$x, akima$y, akima$z, xo=A, yo=B), but it is very slow.

在二维中,approxfun() 函数可以完成这项工作,但我找不到多参数插值的等效函数.

In two dimensions, the approxfun() function would do the job, but I could not find the equivalent for multiple parameters interpolation.

推荐答案

如果你想要一个线性插值,使曲面与所有点交叉,你将无法使用 z = f(x,y),除非数据集已经通过这种函数模拟过.
如果您正在寻找与您的点集匹配的函数 z=f(x,y),则您必须使用 GLM 或 GAM 构建模型.但是,这会导致曲面不会与所有点数据交叉,并且会存在一些残差.

If you want a linear interpolation so that the surface cross all points, you will not be able to interpolate with a function z = f(x,y), except if the dataset has been simulated through this kind of function.
If you are looking for a function z=f(x,y) that matches your point set, you will have to build a model with GLM or GAM for instance. However, this induces that the surface will not cross all points data and there will be some residuals.

因为我过去常常使用空间数据集,这意味着 x 和 y 坐标与 z 观测值,所以我会以这种方式为您提供一些线索.

As I use to work with spatial datasets, which means x and y coordinates with a z observation, I will give you some clues in this way.

首先,我准备了一个用于插值的数据集:

First, I prepare a dataset for interpolation:

library(rgl)
library(akima)
library(dplyr)
library(tidyr)

data(akima)
data.akima <- as.data.frame(akima)
# data visualisation
rgl.spheres(akima$x, akima$z , akima$y,0.5,color="red")
rgl.bbox()

# Dataset for interpolation
seq_x <- seq(min(akima$x) - 1, max(akima$x) + 1, length.out = 20)
seq_y <- seq(min(akima$y) - 1, max(akima$y) + 1, length.out = 20)
data.pred <- dplyr::full_join(data.frame(x = seq_x, by = 1),
                              data.frame(y = seq_y, by = 1)) %>%
  dplyr::select(-by)

然后,我使用你的 akima 插值函数:

Then, I use your akima interpolation function:

# bivariate linear interpolation
# interp:
akima.li <- interp(akima$x, akima$y, akima$z, 
                   xo=seq_x,
                   yo=seq_y)

# interp surface:
rgl.surface(akima.li$x,akima.li$y,akima.li$z,color="green",alpha=c(0.5))
rgl.spheres(akima$x, akima$z , akima$y,0.5,color="red")
rgl.bbox()

使用栅格

从现在开始,如果您想获得某些特定点的插值信息,您可以重新使用 interp 函数或决定使用光栅化图像.使用栅格,您就可以提高分辨率,并获得任何空间位置信息数据.

Using rasters

From now, if you want to get interpolated information on some specific points, you can re-use interp function or decide to work with a rasterized image. Using rasters, you are then able to increase resolution, and get any spatial position information data.

# Using rasters 
library(raster)
r.pred <- raster(akima.li$z, xmn = min(seq_x), xmx = max(seq_x),
       ymn = min(seq_y), ymx = max(seq_y))
plot(r.pred)

## Further bilinear interpolations
## Double raster resolution
r.pred.2 <- disaggregate(r.pred, fact = 2, method = "bilinear")
plot(r.pred.2)

空间插值(反距离插值或克里金法)

在考虑空间插值时,我首先想到的是克里金法.这将平滑您的表面,因此它不会跨越每个数据点.

Spatial interpolation (inverse distance interpolation or kriging)

When thinking in spatial for interpolation, I first think about kriging. This will smooth your surface, thus it will not cross every data points.

# Spatial inverse distance interpolation
library(sp)
library(gstat)
# Transform data as spatial objects
data.akima.sp <- data.akima
coordinates(data.akima.sp) <- ~x+y
data.pred.sp <- data.pred
coordinates(data.pred.sp) <- ~x+y
# Inverse distance interpolation
# idp is set to 2 as weight for interpolation is :
# w = 1/dist^idp
# nmax is set to 3, so that only the 3 closest points are used for interpolation
pred.idw <- idw(
  formula = as.formula("z~1"),
  locations = data.akima.sp, 
  newdata = data.pred.sp,
  idp = 2,
  nmax = 3)

data.spread.idw <- data.pred %>%
  select(-pred) %>%
  mutate(idw = pred.idw$var1.pred) %>%
  tidyr::spread(key = y, value = idw) %>% 
  dplyr::select(-x)

surface3d(seq_x, seq_y, as.matrix(data.spread.idw), col = "green")
rgl.spheres(akima$x, akima$y , akima$z, 0.5, color = "red")
rgl.bbox()

使用 gam 或 glm 进行插值

然而,如果你想找到像 z = f(x,y) 这样的公式,你应该使用具有高自由度的 GLM 或 GAM,这取决于你希望看到的平滑度.另一个优点是您可以添加其他协变量,而不仅仅是 x 和 y.该模型需要拟合 x/y 交互作用.
这是一个简单的 GAM 平滑示例:

Interpolate using gam or glm

However, if you want to find a formula like z = f(x,y), you should use GLM or GAM with high degrees of freedom depending on the smooth you hope to see. Another advantage is that you can add other covariates, not only x and y. The model needs to be fitted with a x/y interaction.
Here an example with a simple GAM smooth:

# Approximation with a gam model
library(mgcv)
gam1 <- gam(z ~ te(x, y), data = data.akima)
summary(gam1)

plot(gam1)
data.pred$pred <- predict(gam1, data.pred)
data.spread <- tidyr::spread(data.pred, key = y, value = pred) %>% 
  dplyr::select(-x)

surface3d(seq_x, seq_y, as.matrix(data.spread), col = "blue")
rgl.spheres(akima$x, akima$y , akima$z, 0.5, color = "red")
rgl.bbox()

这个答案对你来说是正确的方向吗?

Does this answer goes in the right direction for you ?

这篇关于从 akima::interp() 矩阵获取函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆