r3dplotlysurface

3d Surface plots in R - conversion from dataframe to matrix for plot_ly


Does anyone have any advice, or can point me to a resource, to help with converting a dataframe to a matrix for use in a plot_ly 3d surface graph? There are a few questions similar to this, but none of them seem to do the trick.

I have a dataframe df with columns A, B, and C. I'd like to plot A and B on the x-y plane and have C as the z variable.

I can convert my dataframe to a matrix using dfm <- as.matrix(df, rownames.force = NA), then I can call plot_ly and reorder columns like so:

fig <-  plot_ly(z=~dfm[,c(1,3,2)], type = "surface")
fig <- fig %>% add_surface()
fig

but this gives a very strange result: enter image description here

which is not at all what the underlying data looks like.

Any advice here? My hunch is the issue is springing from the conversion to a matrix. If so any pointers on how to map a dataframe's columns onto an x-y-z surface greatly appreciated


Solution

  • What plotly wants in the matrix are z values. The rows of the matrix correspond to y values, and the columns to x values. If your dataframe contains x, y and z values, then converting to this format strongly depends on what kinds of values you have.

    The simplest case would be that your data really corresponds to the format that plotly wants, with x and y values repeated. That's possible, but it's not common.

    A more common case is that you have unstructured x and y locations, and measured z values at each of them. Then you need to do some calculations to put them on a grid. The interp package can do that. For example:

    set.seed(123)
    df <- data.frame(x = rnorm(100), y = rnorm(100, mean = 10), z = rnorm(100, mean = 20))
    xyz <- with(df, interp::interp(x, y, z))
    library(plotly)
    with(xyz, plot_ly(x = ~x, y = ~y, z=~z, type="surface")) 
    

    which produces this: screenshot