如何在R中通过3D数据绘制曲面拟合?

3

我有一个3D散点图,呈现如下:

enter image description here

由于3D数据集非常大,所以我无法在此处包含它。您可以尝试使用标准数据集,如mtcarsiris来回答这个问题。

我的尝试绘制这个3D散点图:

x <- rbind(A_0,A_1,A_2,A_3) 
fig1 <- x %>% plot_ly(x= ~x,y=~y,z = ~z, color= ~key,type="scatter3d", size = 0.5)
fig1 

A_0, A_1, A_2, A_3 是不同的 3*n 数据框(dataframes),它们通过使用rbind组合在一起,并使用每个数据框(dataframe)中包含的键进行区分。

我尝试了各种方法来适应这个表面,比如使用add_surface()add_trace()和将类型更改为'mesh3D'等。

但是,在散点数据上拟合的表面并不是我想要的平滑表面拟合。我得到的错误消息是:z is not a numeric matrix.

有没有更好的方法来拟合这个表面? 我错过了什么吗?

P.S. 我更喜欢使用ggplot()plot_ly()ggplotly()来渲染图表。


我已经发布了一个类似的问题: https://stackoverflow.com/questions/76372502/problem-in-plotting-gam-model-surface-fit-through-plotly-in-r - Rui Miranda
1个回答

5

你可以先使用类似于gam()的方法来进行模型拟合,然后绘制预测结果图。首先,我们可以将GAM拟合到数据上。在本例中,hpwt是两个独立变量(即上图中的xy轴)。而qsec是绘制在z轴上的变量,也是模型中的因变量。

data(mtcars)
library(mgcv)
mod <- gam(qsec ~ te(hp) + te(wt) + ti(hp, wt), data=mtcars)

接下来,我们需要对模型在不同的hpwt组合上进行一些预测。最简单的方法是为每个变量制作一个序列,从它们的最小值到最大值。以下命令就是这样做的,它将制作一个由25个均匀间隔的值组成的序列,从每个自变量的最小值到最大值。

hp.seq <- seq(min(mtcars$hp, na.rm=TRUE), max(mtcars$hp, na.rm=TRUE), length=25)
wt.seq <- seq(min(mtcars$wt, na.rm=TRUE), max(mtcars$wt, na.rm=TRUE), length=25)

接下来,我们可以创建一个生成预测的函数。由于我们将在下面使用outer(),所以函数应该有两个输入,xy。我们要传递的x-y对是用于预测的hpwt的值。该函数创建一个数据帧,其中包含一个观察值和两个变量-hpwt。它使用该新数据帧使用predict()函数从模型生成单个预测。

predfun <- function(x,y){
  newdat <- data.frame(hp = x, wt=y)
  predict(mod, newdata=newdat)
}

接下来,我们将该预测函数应用于我们之前生成的数据序列。我们使用 outer() 函数对每个 hp.seqwt.seq 组合进行外积运算,生成一个 25x25 的预测值矩阵。将 predfun 包装在 Vectorize() 中可防止出现替换长度问题的错误。
fit <- outer(hp.seq, wt.seq, Vectorize(predfun))

最后,我们可以在 plot_ly 中将所有内容组合在一起。我们使用 add_marker() 添加点,并使用 add_surface 添加预测。

plot_ly() %>% 
  add_markers(x = ~mtcars$hp, y=mtcars$wt, z=mtcars$qsec) %>% 
  add_surface(x = ~hp.seq, y = ~wt.seq, z = t(fit))

enter image description here


它运行得很好,但你能解释一下它是如何工作的吗?这样我就可以调整不同的参数来更好地适应。特别是我无法理解这一行代码:mod <- gam(qsec ~ te(hp) + te(wt) + ti(hp, wt), data=mtcars),还有预测函数。 - kolas0202
1
@kolas0202 我在上面添加了一些解释。gam()函数用于拟合广义加性模型。RHS规范(~`te(hp) + te(wt) + ti(hp,wt))拟合了两个变量的平滑交互作用。如果你愿意,你可以用loess模型替换gam:mod <- loess(qsec ~ hp*wt, data=mtcars)`,其余代码将按预期工作。不过,我认为这个例子的要点是,要绘制平滑曲面,你必须对数据进行模型拟合。 - DaveArmstrong
我可以在loess函数中添加公式吗,就像我们通常在二维数据中做的那样,例如 mod <- loess(formula = y~ poly(x, 4, raw = TRUE), data=s)。这对于三维数据也适用吗,以获得曲面拟合,mod <- loess(formula = z ~ poly(x,y, 4,5, raw = TRUE), data=s)? - kolas0202
1
也许吧,但如果你想要一个多项式,我会建议使用lm(z~poly(x, 4, raw=TRUE) + poly(y, 5, raw=TRUE), data=s)。然后,函数的其余部分应该按预期工作。这将创建一个在xy上平滑且非线性的加法模型。 - DaveArmstrong

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