marco11
marco11

Reputation: 245

Fitting a 3D surface to a dataset of points [R]

I have been trying to fit a polynomial surface to a set of point with 3 coordinates.

Let the data be:

DATA <- with(mtcars, as.data.frame(cbind(1:32, wt,disp,mpg)))

I have been trying to draw a surface using:

  1. plot3d from rgl package,
  2. using rsm package,
  3. scatterplot3d package.

For example:

library(scatterplot3d)
attach(mtcars)
DATA <- as.data.frame(cbind(1:32, wt,disp,mpg))
scatterplot3d(wt,disp,mpg, main="3D Scatterplot")
model <- loess(mpg ~wt + disp, data=DATA)
x <-range(DATA$wt)
x <- seq(x[1], x[2], length.out=50)    
y <- range(DATA$disp)
y <- seq(y[1], y[2], length.out=50)
z <- outer(x,y, 
       function(wt,disp)
         predict(model, data.frame(wt,disp)))
z
p <- persp(x,y,z, theta=30, phi=30, 
       col="lightblue",expand = 0.5,shade = 0.2,
       xlab="wt", ylab="disp", zlab="mpg")

I have also tried using surf.ls function:

surf.ls(2,DATA[,2],DATA[,3],DATA[,4])

But what I got looks like this: I don't really know how to transform it to a 3D plot and more importantly, how to get the formula for the best fit surface obtained.

I would really appreciate your help.

PS I have deleted my last post and included more details in this one.

Upvotes: 3

Views: 6633

Answers (2)

Brian D
Brian D

Reputation: 2709

You can plot fitted surfaces with plotly.

Using your example of a fitted model with mtcars dataset:

library(plotly)
data = mtcars
data$fit = predict(loess(mpg ~ wt + disp, data))
p <- plot_ly(data, x= ~disp, y=~wt, z=~mpg, type="scatter3d"); # points
p <- add_trace(p, z=~fit, type="mesh3d") # predicted surface
p

Another example

library(plotly)

dat <- data.frame(ChickWeight) %>%
  mutate(Chick = as.numeric(Chick))

# polynomial (curvy) surfaces:
fit <- lm(weight ~ factor(Diet)*poly(Time, Chick, degree=2), data=dat)

dat$predicted3d <- predict(fit, data=dat)

# points.... 
p <- plot_ly(data = dat, x = ~Time, y = ~Chick, z = ~weight, color = ~Diet, type = "scatter3d", mode="markers", alpha=.95)
# surface 1
p <- add_trace(p, data = dat %>% filter(Diet == 1), x = ~Time, y = ~Chick, z = ~weight, color = ~Diet, type = "mesh3d", opacity=.95)
# surface 2
p <- add_trace(p, data = dat %>% filter(Diet == 2), x = ~Time, y = ~Chick, z = ~weight, color = ~Diet, type = "mesh3d", opacity=.95)
# surface 3
p <- add_trace(p, data = dat %>% filter(Diet == 3), x = ~Time, y = ~Chick, z = ~weight, color = ~Diet, type = "mesh3d", opacity=.95)
# surface 4
p <- add_trace(p, data = dat %>% filter(Diet == 4), x = ~Time, y = ~Chick, z = ~weight, color = ~Diet, type = "mesh3d", opacity=.95)

p

surface plot of chick weight model

Upvotes: 0

Clay
Clay

Reputation: 2726

Try this:

attach(mtcars)
DATA <- as.data.frame(cbind(1:32, wt,disp,mpg))

x_wt <- DATA$wt
y_disp <- DATA$disp
z_mpg <- DATA$mpg

fit <- lm(z_mpg ~ poly(x_wt, y_disp, degree = 2), data = DATA)

To plot with rsm, use the following:

library(rsm)
image(fit, y_disp ~ x_wt)
contour(fit, y_disp ~ x_wt)
persp(fit, y_disp ~ x_wt, zlab = "z_mpg")

To plot with ggplot, use the following:

## ggplot
# Use rsm package to create surface model.
library(rsm)
SurfMod <- contour(fit, y_disp ~ x_wt)

# extract list values from rsm Surface Model 
Xvals <- SurfMod$`x_wt ~ y_disp`[1]
Yvals <- SurfMod$`x_wt ~ y_disp`[2]
Zvals <- SurfMod$`x_wt ~ y_disp`[3]

# Construct matrix with col and row names 
SurfMatrix <- Zvals$z
colnames(SurfMatrix) <- Yvals$y
rownames(SurfMatrix) <- Xvals$x

# Convert matrix to data frame
library(reshape2)
SurfDF <- melt(SurfMatrix)

library(ggplot2)
gg <- ggplot(data = SurfDF) +
      geom_tile(data = SurfDF, aes(Var1, Var2,z = value, fill = value)) +
      stat_contour(data = SurfDF, aes(Var1, Var2, z = value, color = ..level..)) +
      scale_colour_gradient(low = "green", high = "red") +
      geom_point(data = DATA, aes(wt, disp, z = mpg, color = mpg)) +
      geom_text(data = DATA, aes(wt, disp,label=mpg),hjust=0, vjust=0) +
      scale_fill_continuous(name="mpg") +
      xlab("x_wt") +
      ylab("y_disp")
library(directlabels)
direct.label.ggplot(gg, "angled.endpoints")

To see all of the available direct.label methods, go to http://directlabels.r-forge.r-project.org/docs/index.html

Upvotes: 8

Related Questions