在 R Plotly 中用曲面椭圆绘制 Ellipse3d曲面、椭圆、中用、Plotly

2023-09-07 08:44:03 作者:为{幸葍}努か

与这里的问题类似,但这并没有给我明确的需求,我无法弄清楚:

Similar to the question here but this didn't give me excatly what I needed and I couldn't figure it out: Plot ellipse3d in R plotly?. I want to recreate rgl's ellipse3d and surface ellipsoid in plotly. I know there there was an anwer which allowed plotting of an ellipse but as individual opaque markers, I need to get it as a surface ellipsoid that's slightly opaque so I can still see the data points in the ellipsoid.

Create 3D Scatter Plot Python Plotly

I tried to figure out how dww's comment for "add_surface" instead works but couldn't figure it out.... Can anyone help please?

if (!require("rgl")) install.packages("rgl")
dt <- cbind(x = rnorm(100), y = rnorm(100), z = rnorm(100))
ellipse <- ellipse3d(cov(dt))
plot3d(dt)
plot3d(ellipse, add = T, color = "red", alpha = 0.5)

dww's answer was:

if (!require("plotly")) install.packages("plotly")
if (!require("rgl")) install.packages("rgl")
dt <- cbind(x = rnorm(100), y = rnorm(100), z = rnorm(100))
ellipse <- ellipse3d(cov(dt))

p <- plot_ly(mode = 'markers') %>% 
  add_trace(type = 'scatter3d', size = 1, 
  x = ellipse$vb[1,], y = ellipse$vb[2,], z = ellipse$vb[3,], 
  opacity=0.01) %>% 
  add_trace(type = 'scatter3d', x = dt[,1], y = dt[,2], z = dt[,3])
p

# shows more obviously what dww's code does to create the visual ellipsoid
w <- plot_ly(mode = 'markers') %>% 
  add_trace(type = 'scatter3d',  
  x = ellipse$vb[1,], y = ellipse$vb[2,], z = ellipse$vb[3,], 
  opacity=0.5) %>% 
  add_trace(type = 'scatter3d', x = dt[,1], y = dt[,2], z = dt[,3])
w

Their comment on how to use add_surface was

Note that for simplicity, I plotted the ellipse as a cloud using markers. If you want to use add_surface instead, you will have to first convert the ellipse into a different format, with a vector of x locations, a vector of y locations, z as a matrix (dimensions equal to x by y). You'll also need to split the z values into two separate surface layers one for the top half of the ellipsoid and one for the bottom. I don't have time right now to do all this, but if you get stuck I can work this out later

解决方案

This is my solution if anyone is interested in it. This allows using of the buttons in plotly to toggle the ellipsoid on and off so that you can still hover over and select data points inside the ellipsoid when desired:

if (!require("rgl")) install.packages("rgl", dependencies=TRUE, repos="http://cran.rstudio.com/")
if (!require("plotly")) install.packages("plotly", dependencies=TRUE, repos="http://cran.rstudio.com/")    
dt <- cbind(x = rnorm(100), y = rnorm(100), z = rnorm(100))
ellipse <- ellipse3d(cov(dt))

updatemenus <- list(
  list(
    active = 0,
    type= 'buttons',
    buttons = list(
      list(
        label = "Ellipsoid",
        method = "update",
        args = list(list(visible = c(TRUE, TRUE)))),
      list(
        label = "No Ellipsoid",
        method = "update",
        args = list(list(visible = c(TRUE, FALSE)))))
  )
)

plot<- plot_ly()%>%
  # Plot raw scatter data points
  add_trace(data = dt, x = dt[,1], y = dt[,2], z = dt[,3],
            type = "scatter3d", mode = 'markers', marker = list(size = 3))  %>%
  # Plot ellipsoid 
  add_trace(x=ellipse$vb [1,], y=ellipse$vb [2,], z=ellipse$vb [3,], 
            type='mesh3d', alphahull = 0, opacity = 0.4)%>%
  # Axes Titles
  layout(updatemenus = updatemenus)
plot