Lince202
Lince202

Reputation: 143

How to plot loess surface with ggplot

i have this code and i create a loess surface of my dataframe.

    library(gstat)
    library(sp)
    x<-c(0,55,105,165,270,65,130,155,155,225,250,295,
         30,100,110,135,160,190,230,300,30,70,105,170,
         210,245,300,0,85,175,300,15,60,90,90,140,210,
         260,270,295,5,55,55,90,100,140,190,255,285,270)
    y<-c(305,310,305,310,310,260,255,265,285,280,250,
         260,210,240,225,225,225,230,210,215,160,190,
         190,175,160,160,170,120,135,115,110,85,90,90,
         55,55,90,85,50,50,25,30,5,35,15,0,40,20,5,150)
    z<-c(870,793,755,690,800,800,730,728,710,780,804,
         855,813,762,765,740,765,760,790,820,855,812,
         773,812,827,805,840,890,820,873,875,873,865,
         841,862,908,855,850,882,910,940,915,890,880,
         870,880,960,890,860,830)

    dati<-data.frame(x,y,z)

    x.range <- as.numeric(c(min(x), max(x)))  
    y.range <- as.numeric(c(min(y), max(y)))

    meuse.loess <- loess(z ~ x * y, dati, degree=2, span = 0.25, 
                         normalize=F)
    meuse.mar <- list(x = seq(from = x.range[1], to = x.range[2], by = 1), y = seq(from = y.range[1], 
                                                                                    to = y.range[2], by = 1))
    meuse.lo <- predict(meuse.loess, newdata=expand.grid(meuse.mar), se=TRUE)

Now I want to plot meuse.lo[[1]] with ggplot2 function... but i don't know how to convert meuse.lo[[1]] in a dataframe with x,y (grid's coordinates) and z (interpolated value) columns. Thanks.

Upvotes: 2

Views: 1170

Answers (2)

Andrie
Andrie

Reputation: 179438

Your problem here is that loess() returns a matrix if you use grid.expand() to generate the new data for loess().

This is mentioned in the help for ?loess.predict:

If newdata was the result of a call to expand.grid, the predictions (and s.e.'s if requested) will be an array of the appropriate dimensions.

Now, you can still use grid.expand() to compute the new data, but force this function to return a data frame and dropping the attributes.

From ?grid.expand:

KEEP.OUT.ATTRS: a logical indicating the "out.attrs" attribute (see below) should be computed and returned.

So, try this:

nd <- expand.grid(meuse.mar, KEEP.OUT.ATTRS = FALSE)
meuse.lo <- predict(meuse.loess, newdata=nd, se=TRUE)

# Add the fitted data to the `nd` object
nd$z <- meuse.lo$fit

library(ggplot2)
ggplot(nd, aes(x, y, col = z)) + 
  geom_tile() +
  coord_fixed()

The result:

enter image description here

Upvotes: 1

adaien
adaien

Reputation: 1942

ggplot2 is probably not the best choice for 3d graphs. However here is an easy solution with rgl

library(rgl)
plot3d(x, y, z, type="s", size=0.75, lit=FALSE,col="red")
surface3d(meuse.mar[[1]], meuse.mar[[2]], meuse.lo[[1]],
      alpha=0.4, front="lines", back="lines")

Upvotes: 1

Related Questions