Black Lives Matter. Please consider donating to Black Girls Code today.

Droplines from points in 3D scatterplot?

Hi,

I’ve made a 3D scatterplot in R and I would like to add droplines from the points down to the x-y plane. How can I do this? I haven’t found any documentation online.

Here’s my code so far:

p <- plot_ly(MDSout2, x = ~MDS1, y = ~MDS2, z = ~MDS3, color = ~moisture, colors = c(‘orange’, ‘green’, ‘blue’), marker = list(size = 4)) %>%
add_markers() %>%
layout(scene = list(xaxis = list(title = ‘MDS1’),
yaxis = list(title = ‘MDS2’),
zaxis = list(title = ‘MDS3’)))

p

Thanks!

I can’t reproduce your example, but don’t you get something like this?

plot_ly(x = 1:10, y = 10:1, z = 1:10)

Thanks for your response! It’s indeed possible to get the lines to show when I highlight the point with my cursor, but what I’d like is permanent lines from each point down to the x-y plane. For example, when using scatterplot3d(), this can be done by simply adding the line type="h" like in this example:

library(scatterplot3d)
with(mtcars, {
  scatterplot3d(disp, wt, mpg,           # x y and z axis
                color="blue", pch=19,    # filled blue circles
                type="h",                # lines to the horizontal plane
                main="3-D Scatterplot Example",
                xlab="Displacement (cu. in.)",
                ylab="Weight (lb/1000)",
                zlab="Miles/(US) Gallon")
})

But plotly looks so much better and is more versatile than scatterplot3d()… Any suggestions? Thanks!

Ah, I see, this would be a lot easier if add_segments() knew about z coordinates, so I’ve opened an issue here

In the meantime, you can do a bit of data wrangling to get there

library(plotly)

mtcars$id <- seq_len(nrow(mtcars))
ms <- replicate(2, mtcars, simplify = F)
ms[[2]]$mpg <- 0
m <- group2NA(dplyr::bind_rows(ms), "id")
  
plot_ly(color = I("black"), showlegend = F) %>%
  add_markers(data = mtcars, x = ~disp, y = ~wt, z = ~mpg) %>%
  add_paths(data = m, x = ~disp, y = ~wt, z = ~mpg)

1 Like

Wow, thanks, this looks promising. Unfortunately when I copy/paste your code into RStudio I get the following error message:

Error: Do not know how to find data associated with x

This is in response to the last line (everything else works fine):

add_paths(data = m, x = ~disp, y = ~wt, z = ~mpg)

Do you know why this happens?

hmm, what does head(m) give you?

head(m)
[1] 1 2 3 4 5 6

m should be a data frame, not a vector. Not sure why that’s happening for you…

1 Like

Ah! I hadn’t created the group2NA() function properly. Now I copied/pasted your whole code from https://github.com/ropensci/plotly/blob/master/R/group2NA.R and it works. Now I can get the example to work, which is great!

One puzzle remains when I try to apply this to my data. If I use plot_ly(color = I("black"), showlegend = F), then it works just like in the example. BUT if I want to change the color of the points by category by instead using plot_ly(color = ~cover, showlegend = T), then I get lines from one point to the next in addition to the lines to the floor. This is all the more weird that it works fine in the example, using for instance plot_ly(color = ~am, showlegend = F). I’m going to have to work on getting rid of those extra lines; any suggestions would be most welcome.

Thanks for your patience, I’m learning a lot.

OK I figured that last issue out: for some reason it doesn’t work if it’s not numeric data. I had different categories (like “hardwood” and “mixed” for canopy type) and it made these weird extra lines. Then I changed it to ones and twos and it worked fine. It messes up the legend but that’s a minor issue.

Thanks for helping me figure out this work around. I hope a more straightforward solution will be worked out, but this is great.

Oh, for some reason I thought group2NA() was exported (i.e., accessible to end users without using :::). I’ve actually been working on speeding up this function and this example has me convinced it should be exported.

Anyway, you can try out the new functionality (which fixes a bug relevant to this example) by doing devtools::install_github("ropensci/plotly#1022"). Then,

library(plotly)
library(dplyr)

mtcars$id <- seq_len(nrow(mtcars))
ms <- replicate(2, mtcars, simplify = F)
ms[[2]]$mpg <- 0
m <- ms %>%
  bind_rows() %>%
  group2NA("id", "vs")

plot_ly(color = ~factor(vs), showlegend = F) %>%
  add_markers(data = mtcars, x = ~disp, y = ~wt, z = ~mpg) %>%
  add_paths(data = m, x = ~disp, y = ~wt, z = ~mpg)

Is there a way of using something similiar, like when type=“h” to plot the dropping lines onto our plane of gradients?