Add Regression Plane to 3D Scatter Plot in Plotly

Add Regression Plane to 3d Scatter Plot in Plotly

You need to sample the points based on the predict object created from your lm call. This creates a surface similar to the volcano object which you can then add to your plot.

library(plotly)
library(reshape2)

#load data

my_df <- iris
petal_lm <- lm(Petal.Length ~ 0 + Sepal.Length + Sepal.Width,data = my_df)

The following sets up the extent of our surface. I chose to sample every 0.05 points, and use the extent of the data set as my limits. Can easily be modified here.

#Graph Resolution (more important for more complex shapes)
graph_reso <- 0.05

#Setup Axis
axis_x <- seq(min(my_df$Sepal.Length), max(my_df$Sepal.Length), by = graph_reso)
axis_y <- seq(min(my_df$Sepal.Width), max(my_df$Sepal.Width), by = graph_reso)

#Sample points
petal_lm_surface <- expand.grid(Sepal.Length = axis_x,Sepal.Width = axis_y,KEEP.OUT.ATTRS = F)
petal_lm_surface$Petal.Length <- predict.lm(petal_lm, newdata = petal_lm_surface)
petal_lm_surface <- acast(petal_lm_surface, Sepal.Width ~ Sepal.Length, value.var = "Petal.Length") #y ~ x

At this point, we have petal_lm_surface, which has the z value for every x and y we want to graph. Now we just need to create the base graph (the points), adding color and text for each species:

hcolors=c("red","blue","green")[my_df$Species]
iris_plot <- plot_ly(my_df,
x = ~Sepal.Length,
y = ~Sepal.Width,
z = ~Petal.Length,
text = ~Species, # EDIT: ~ added
type = "scatter3d",
mode = "markers",
marker = list(color = hcolors))

and then add the surface:

iris_plot <- add_trace(p = iris_plot,
z = petal_lm_surface,
x = axis_x,
y = axis_y,
type = "surface")

iris_plot

Sample Image

How to add Planes in a 3D Scatter Plot

I think you might be looking for the add_trace function in plotly so you can just create the surfaces and then add them to the figure:

Also, note, there's definitely ways to simplify this code, but for a general idea:

import plotly.express as px
import pandas as pd
import plotly.graph_objects as go
import numpy as np

fig = px.scatter_3d(df, x='Functionality ', y='Accessibility', z='Immersion', color='Platforms')

bright_blue = [[0, '#7DF9FF'], [1, '#7DF9FF']]
bright_pink = [[0, '#FF007F'], [1, '#FF007F']]
light_yellow = [[0, '#FFDB58'], [1, '#FFDB58']]

# need to add starting point of 0 to each dimension so the plane extends all the way out
zero_pt = pd.Series([0])
z = zero_pt.append(df['Immersion'], ignore_index = True).reset_index(drop = True)
y = zero_pt.append(df['Accessibility'], ignore_index = True).reset_index(drop = True)
x = zero_pt.append(df['Functionality '], ignore_index = True).reset_index(drop = True)

length_data = len(z)
z_plane_pos = 40*np.ones((length_data,length_data))

fig.add_trace(go.Surface(x=x, y=y, z=z_plane_pos, colorscale=light_yellow, showscale=False))
fig.add_trace(go.Surface(x=x.apply(lambda x: 10), y=y, z = np.array([z]*length_data), colorscale= bright_blue, showscale=False))
fig.add_trace(go.Surface(x=x, y= y.apply(lambda x: 30), z = np.array([z]*length_data).transpose(), colorscale=bright_pink, showscale=False))

Sample Image

Add regression plane in R using Plotly

Here is an illustrative example that shows how the observed points and the regression plane can be plotted together in a 3D plot generated using the plotlty package.

Hope it can help you.

### Data generating process
set.seed(1234)
n <- 50
x1 <- runif(n); x2 <- runif(n)
x3 <- rnorm(n)>0.5
y <- 2*x1-x2+rnorm(n, sd=0.25)
df <- data.frame(y, x1, x2, x3)

### Estimation of the regression plane
mod <- lm(y ~ x1+x2)
cf.mod <- coef(mod)

### Calculate z on a grid of x-y values
x1.seq <- seq(min(x1),max(x1),length.out=25)
x2.seq <- seq(min(x2),max(x2),length.out=25)
z <- t(outer(x1.seq, x2.seq, function(x,y) cf.mod[1]+cf.mod[2]*x+cf.mod[3]*y))

#### Draw the plane with "plot_ly" and add points with "add_trace"
cols <- c("#f5cb11", "#b31d83")
cols <- cols[x3+1]
library(plotly)
p <- plot_ly(x=~x1.seq, y=~x2.seq, z=~z,
colors = c("#f5cb11", "#b31d83"),type="surface") %>%
add_trace(data=df, x=x1, y=x2, z=y, mode="markers", type="scatter3d",
marker = list(color=cols, opacity=0.7, symbol=105)) %>%
layout(scene = list(
aspectmode = "manual", aspectratio = list(x=1, y=1, z=1),
xaxis = list(title = "X1", range = c(0,1)),
yaxis = list(title = "X2", range = c(0,1)),
zaxis = list(title = "Y", range = pretty(z)[c(1,8)])))
print(p)

Here is the 3D plot generated by the above code:

Sample Image

How do I add surfaces such a planes as traces generated mathematical formulas in a 3D scatter plot in plotly in r?

Add inherit=FALSE inside add_trace:

p <- plot_ly(df, x = ~x, y = ~y, z = ~z, color = ~col, colors=c('#BF382A', '#0C4B8E')) %>%
add_markers() %>%
add_trace(z=surface2, x=axis_x, y=axis_y, type="surface", inherit=FALSE) %>%
layout(scene = list(xaxis = list(title = 'X'), yaxis = list(title = 'Y'),
zaxis = list(title = 'Z'), aspectmode='cube'))
print(p)

Sample Image

Plot 3d plane from x+y+z=6 equation in plotly

When x <- seq(from=-10, to=10, by=1); y<-seq(from=-10, to=10, by=1), x+y+z=6 is not plane but line.

You need to prepare more data points.

library(dplyr); library(tidyr); library(plotly)

x <- seq(from=-10, to=10, by=1)
y <- seq(from=-10, to=10, by=1)
z1 <- 6-x-y #For the first plane

origin <- tibble(x = x, y = y, z = z1)
# prepare all combination of x and y, and calculate z1
xyz1 <- tidyr::crossing(x, y) %>%
mutate(z1 = 6-x-y)

plot_ly(x = ~x, y = ~y, z = ~z1, type = "mesh3d", data = xyz1) %>%
add_markers(~ x, ~y, ~z1, data = origin)

Orange points are the data you prepare (when x <- seq(from=-10, to=10, by=1); y<-seq(from=-10, to=10, by=1) , x+y+z=6 is line.)
Sample Image



Related Topics



Leave a reply



Submit