Search code examples
r3dplotlyscatter-plot

Adding scatterplot to existing scatterplot in plot_ly in R


I wish to add scatterplots to an existing 3D scatterplot in R using plot_ly. I am generating data from Normal distribution of length 219. Then I want to plot and add scatter plots corresponding to the indices 80, 150 and 195 of the variables on the same graph with a different color (red in my case).

I used the following codes -

library(plotly)
index <- c(80, 150, 195)
set.seed(4991)
data1 <- rnorm(219,9,1.5)
data2 <- rnorm(219,2,1)
timeline <- 1:length(data1)

plot_ly(x=data1, y=data2, z=timeline, type="scatter3d", mode="markers")%>%
  layout(scene = list(xaxis = list(title = 'cases per day'),
                      yaxis = list(title = 'deaths per day'),
                      zaxis = list(title = 'observation #')))%>%
  add_trace(x=data1[index],y=data2[index],z=timeline[index], type="scatter3d", mode = "markers", marker = list(size = 5, color = "red", symbol = 104))

Snapshot of the output looks like this - enter image description here

However if I use the color=timeline option in the plot_ly section,

plot_ly(x=data1, y=data2, z=timeline, type="scatter3d", mode="markers",color=timeline)%>%
  layout(scene = list(xaxis = list(title = 'cases per day'),
                      yaxis = list(title = 'deaths per day'),
                      zaxis = list(title = 'observation #')))%>%
  add_trace(x=data1[index],y=data2[index],z=timeline[index], type="scatter3d", mode = "markers", marker = list(size = 5, color = "red", symbol = 104))

I get the following error

Error:
! Tibble columns must have compatible sizes.
• Size 3: Columns `x`, `y`, and `z`.
• Size 219: Column `color`.
ℹ Only values of size one are recycled.
Run `rlang::last_error()` to see where the error occurred.

I want to plot the 3D scatterplot with color=timeline option and then add the scatterplot in red. Any help is appreciated.


Solution

  • The variable timeline is all unique values, which doesn't align with your desire to have the three values colored. What you need is a grouping variable (i.e., yes or no, a or b, etc.)

    I made a control.

    timeline1 <- rep("A", length(data1))
    timeline1[index] <- "B"
    summary(timeline1 %>% as.factor())
    #   A   B 
    # 216   3  
    

    Then I made my graph. One trace- with specific colors designated. I used Plotly's blue to keep it consistent with your question.

    # '#1f77b4' is the Plotly blue (muted blue)
    plot_ly(x = data1, y = data2, z = timeline, type = "scatter3d", mode = "markers",
            color = timeline1, colors = setNames(c('#1f77b4', "red"), nm = c("A", "B"))) %>%
      layout(scene = list(xaxis = list(title = 'cases per day'),
                          yaxis = list(title = 'deaths per day'),
                          zaxis = list(title = 'observation #')))
    

    enter image description here enter image description here