Search code examples
rplotlycontourr-plotlysurface

Add a permanent contour line to a surface plot in R plotly


I am using the plotly package in R to draw a surface plot and a contour plot:

# Load package
library(plotly)

# Simulate the data for plotting
x <- y <- seq(from = 0, to = 100, by = 1)
z1 <- outer(X = x, Y = y, FUN = function(x, y) x^0.2 * y^0.3) # data for surface plot

# Draw surface plot (3D)
plotly::plot_ly(z = z1) %>%
  plotly::add_surface(
    contours = list(
      z = list(
        show = TRUE,
        usecolormap = TRUE,
        highlightcolor = "#ff0000",
        project = list(z = TRUE)
      ) 
    )    
  ) 

# Draw contour plot (2D)
plot_ly(z = z1) %>%
  add_contour()

The rendering of the two plots contains contour lines, which show the combinations of x and y that yield a constant z level. In the case of the 3D surface plot, hovering the mouse over it dynamically draws a contour line where the mouse is with a projection of the contour line on one of the sides of the 3-dimensional space.

What I would like to do is to manually draw one or multiple contour lines on the two plots by specifying a value for z myself (e.g. z = 5).


Solution

  • Thanks to @IRTFM's comment, I was able to find an answer to my question. The answer is more specific to contour plots. The user needs to set the start and end attributes under the contours argument to the desired z value. Below, I plot the contour line for z = 5:

    # Load package
    library(plotly)
    
    # Simulate the data for plotting
    x <- y <- seq(from = 0, to = 100, by = 1)
    z1 <- outer(X = x, Y = y, FUN = function(x, y) x^0.2 * y^0.3) # data for surface plot
    
    plot_ly(
      z = z1,
      type = "contour",
      autocontour = FALSE,    
      colorscale = "RdBu",
      
      contours = list(
        start = 5,
        end = 5,
        showlabels = TRUE,
        showlines = TRUE,
        coloring = "lines"
      )
      
    ) %>%
     hide_guides()
    

    Contour line z = 5

    In case one wants to plot 2 specific contour lines, they need an additional argument: ncontours = 2. Not doing so will likely lead to the plotting of more than 2 contour lines - the lines for which the z value is between start and end.

    plot_ly(
      z = z1,
      type = "contour",
      autocontour = FALSE,
      
      ncontours = 2,
      
      colorscale = "RdBu",
      
      contours = list(
        start = 5,
        end = 7,
        showlabels = TRUE,
        showlines = TRUE,
        coloring = "lines"
      )
      
    ) %>%
     hide_guides()
    

    Two contour lines, z=5 and z=7

    Finally, for more than 2 specific contour lines, we need to use the add_contour() function. Let's plot 4 specific contour plots:

    plot_ly(
      z = z1,
      type = "contour",
      autocontour = FALSE,
      
      ncontours = 2,
      
      colorscale = "RdBu",
      
      contours = list(
        start = 5,
        end = 7,
        showlabels = TRUE,
        showlines = TRUE,
        coloring = "lines"
      )
      
    ) %>% 
      
      add_contour(
        
        ncontours = 2,
        
        contours = list(
          start = 4,
          end = 6,
          showlabels = TRUE,
          showlines = TRUE,
          coloring = "lines"
        )
        
      ) %>%
      
      hide_guides()
    

    Four contour plots