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

kol*_*202 3 3d r ggplot2 shiny plotly

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

在此输入图像描述

3D 数据集非常大,因此我无法将其包含在此处。mtcars人们可以尝试使用标准数据集(如或 )来回答这个问题iris。

我尝试绘制这个 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 
Run Code Online (Sandbox Code Playgroud)

A_0, A_1, A_2, A_3是不同的 3*n ,使用每个中包含的密钥dataframes组合在一起并区分rbinddataframe

我尝试通过各种方法拟合表面,例如add_surface(),add_trace()将类型更改为'mesh3D'

但是,最终的表面拟合不是我想要的,我需要通过此散射数据进行平滑的表面拟合。我收到的错误是这样的:z is not a numeric matrix.

有没有更好的方法来拟合表面,我在这里缺少什么?

ggplot()PS 我更喜欢用, plot_ly(),渲染绘图ggplotly()。

Dav*_*ong 5

您可以首先使用类似的方法拟合模型gam(),然后绘制预测。首先,我们可以将 GAM 拟合到数据。在本例中,hp和wt是两个自变量(即上图中的 轴x和轴)。是绘制在 z 轴上的变量,是模型中的因变量。yqsec

data(mtcars)
library(mgcv)
mod <- gam(qsec ~ te(hp) + te(wt) + ti(hp, wt), data=mtcars)
Run Code Online (Sandbox Code Playgroud)

hp接下来,我们需要在和的不同组合下对模型进行一些预测wt。最简单的方法是为每个变量创建一个从最小值到最大值的值序列。这就是下面的命令的作用。它生成一个由 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)
Run Code Online (Sandbox Code Playgroud)

接下来,我们可以创建一个生成预测的函数。因为我们将outer()在下面使用,所以我们应该让该函数接受两个输入 andx和 a y。我们要传入的 xy 对是预测的值hp并wt用于预测。该函数创建一个数据框,其中包含一个观察值和两个变量 -hp和wt。它使用该新数据框通过该函数从模型生成单个预测predict()。

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

接下来,我们将该预测函数应用于我们上面制作的数据序列。我们使用outer()外积函数为hp.seq和的每个组合创建一个 25x25 的预测值矩阵wt.seq。包裹可以防止有关替换长度predfun问题Vectorize()的错误。

fit <- outer(hp.seq, wt.seq, Vectorize(predfun))
Run Code Online (Sandbox Code Playgroud)

最后,我们可以将所有内容放在一起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))

Run Code Online (Sandbox Code Playgroud)

在此输入图像描述