rggplot2plotly

Weird Contour plot from ggplot


I have drawn a contour plot using ggplot2 package as below

library(ggplot2)
mydat = structure(list(Col1 = c(65L, 65L, 65L, 65L, 65L, 65L, 65L, 65L, 
265L, 265L, 265L, 265L, 265L, 265L, 265L, 265L, 515L, 515L, 515L, 
515L, 515L, 515L, 515L, 515L, 765L, 765L, 765L, 765L, 765L, 765L, 
765L, 765L, 1015L, 1015L, 1015L, 1015L, 1015L, 1015L, 1015L, 
1015L, 1265L, 1265L, 1265L, 1265L, 1265L, 1265L, 1265L, 1265L, 
1515L, 1515L, 1515L, 1515L, 1515L, 1515L, 1515L, 1515L, 2015L, 
2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L), Col2 = c(5L, 
6L, 7L, 8L, 9L, 10L, 11L, 15L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 
15L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 15L, 5L, 6L, 7L, 8L, 9L, 10L, 
11L, 15L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 15L, 5L, 6L, 7L, 8L, 
9L, 10L, 11L, 15L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 15L, 5L, 6L, 
7L, 8L, 9L, 10L, 11L, 15L), Value = c(0.68378, 0.68815, 0.68754, 
0.68887, 0.68742, 0.68857, 0.68758, 0.68789, 0.67, 0.70059, 0.70054, 
0.69983, 0.69921, 0.70505, 0.70422, 0.70567, 0.66182, 0.67798, 
0.67769, 0.67904, 0.68013, 0.6867, 0.68662, 0.68569, 0.67497, 
0.70433, 0.70314, 0.70737, 0.70684, 0.70739, 0.70696, 0.7077, 
0.67808, 0.69216, 0.69106, 0.69153, 0.69172, 0.70421, 0.70419, 
0.70416, 0.65267, 0.65736, 0.66198, 0.69238, 0.69056, 0.69074, 
0.69193, 0.69187, 0.68101, 0.70799, 0.70821, 0.70827, 0.70846, 
0.70803, 0.70902, 0.70768, 0.64015, 0.6744, 0.67539, 0.67862, 
0.68034, 0.68014, 0.67996, 0.67873)), class = "data.frame", row.names = c(NA, 
-64L))

ggplot(mydat,  aes(Col1, Col2, z = Value)) +
        geom_raster(aes(fill = Value)) +
        geom_contour(aes(colour = Value))

As can be seen, above code generates some weird looking contour plot.

I also tried to draw a contour plot using plotly::plot_ly based on below code, which appears to be more reasonable

plotly::plot_ly(x = sort(unique(mydat$Col1)), y = sort(unique(mydat$Col2)), z = matrix(mydat$Value, nr = 8)) %>% plotly::add_surface(contours = list(z = list(show=TRUE,usecolormap=TRUE,highlightcolor="#ff0000",project=list(z=TRUE))))

Could you please help to understand if there is anything incorrect in my approach based on ggplot and how can I make that plot more eye-smoothing?

Many thanks for your time and pointer.


Solution

  • There may be other options in ggplot2 that I am not familiar with, but it seems like you may need to interpolate your data if you want a smoother display. It may also be helpful to add the original data points to the plot so as not to imply that your original data is so well distributed across the plotted space.

    This is your original plot, which shows the missing areas without data:

    # without interpolation
    ggplot(mydat,  aes(Col1, Col2, z = Value)) +
      geom_raster(aes(fill = Value), interpolate = FALSE) +
      geom_contour(aes(colour = Value))
    

    enter image description here

    Turning on intrerpolation doesn't help much here (again, there may be further options that I am not aware of):

    # with interpolation
    ggplot(mydat,  aes(Col1, Col2, z = Value)) +
      geom_raster(aes(fill = Value), interpolate = TRUE) +
      geom_contour(aes(colour = Value))
    

    enter image description here

    One solution is to interpolate with akima, and plot those resulting smoothed values. Again, I suggest marking the locations of the original data:

    # interpolation with akima package
    library(akima)
    M <- with(mydat, expr = interp(x = Col1, y = Col2, z = Value))
    image(M)
    
    # reshape to data.frame
    newdat <- expand.grid(Col1 = M$x, Col2 = M$y, stringsAsFactors = F)
    newdat$Value <- c(M$z)
    
    # plot
    ggplot(newdat,  aes(Col1, Col2, z = Value)) +
      geom_raster(aes(fill = Value)) +
      geom_contour(aes(colour = Value)) + 
      geom_point(data = mydat)
    

    enter image description here