Search code examples
rggplot2dataframeloess

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.


Solution

  • 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