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
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))
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:
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)
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.)
Related Topics
R - Faster Way to Calculate Rolling Statistics Over a Variable Interval
Reading Big Data with Fixed Width
Replace Specific Values Based on Another Dataframe
First Day of the Month from a Posixct Date Time Using Lubridate
In Read.Table(): Incomplete Final Line Found by Readtableheader
Assign Names to Data Frame with As.Data.Frame Function
Remove Text After Final Period in String
Dplyr Rowwise Sum and Other Functions Like Max
Handling Errors Before Warnings in Trycatch
Rjava Linker Error Licuuc with Anaconda & Fopenmp Error Without Anaconda for MACos Sierra 10.12.4
Fitting a Curve to Specific Data
How to Plot a Normal Distribution by Labeling Specific Parts of the X-Axis
Reading Information from a Password Protected Site
How to Sort a Character Vector According to a Specific Order
How to Have Na's Displayed First Using Arrange()
How to Turn Gpclibpermit() to True