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

I have a set of equations (z1) x+y+z=6, (z2) x+2y+2z=9 and (z3) x+3y+4z=13 and would like to plot the planes using plotly.
Method1: using mesh3d
require(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
fig <- plot_ly(x = ~, y = ~y, z = ~z1, type = 'mesh3d')
fig
Produces no output though. Why?
Method 2: Using surface
Whereas this produces a plane but the wrong one.
library(plotly)
x<-seq(from=-10,to=10,by=1)
y<-seq(from=-10,to=10,by=1)
z1<-6-x-y
z1<-matrix(rep(z1,10),NROW(x),10)
fig <- plot_ly(showscale = FALSE)
fig <- fig %>% add_surface(z = ~z1)
fig
This plane is not correct. If you look at the point x=2, y=2, z should equal 2 but it doesn't. Instead it is 22, and that's not correct.

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

Surface of a matrix with plotly in R distorted

I have the following code example in R to visualize a surface generated as an interpolation from points.
library(plotly)
test_data=read.csv("test_data.csv")
x<- test_data$x
y<- test_data$y
z<- test_data$z
fit_loess=loess(z ~ x + y , degree = 0,span=0.54)
min_x <- min(x)
max_x <- max(x)
min_y <- min(y)
max_y <- max(y)
griddf <- expand.grid(x = (seq(min_x,max_x,length.out = 10)),
y = (seq(min_y,max_y,length.out = 10)))
p_loess <- data.frame(griddf)
p_loess$z <- predict(fit_loess, p_loess)
fig <- plot_ly()
fig <- fig %>% add_surface(z = ~xtabs(z ~ x + y, data = p_loess),
x = seq(min_x,max_x,length.out = 10),
y =seq(min_y,max_y,length.out = 10),colorbar=list(title = 'z'))
fig <- fig %>% add_markers( x = ~x, y = ~y, z = ~z,
marker = list(color = 'rgb(17, 157, 255)',size = 3))
fig
According my question in Question ID 73946202 , I am using xtabs for matrix generation.
But the result of the surface of plotly is distorted to the measurement points. I am not able to find the reason for that.
test_data.csv:
"","x","y","z"
"1",1.97494896,9.99449486,54.9318
"2",1.97493756666667,9.9945128,54.970222222222
"3",1.97492473333333,9.9945292333333,55.060666666667
"4",1.97491141666667,9.9945450333333,55.415
"5",1.97489883333333,9.9945608833333,55.639666666667
"6",1.97488585,9.99457735,55.742166666667
"7",1.97487323333333,9.9945934166667,55.772333333333
"8",1.97486086666667,9.9946095833333,55.953333333333
"9",1.97485151666667,9.99462525,55.970166666667
"10",1.97483576666667,9.9946413166667,56.0495
"11",1.97506965,9.9945288666667,55.070333333333
"12",1.9750572,9.99454545,55.196666666667
"13",1.97504416666667,9.9945614,55.305
"14",1.97503078333333,9.9945772833333,55.375166666667
"15",1.97501828333333,9.9945933333333,55.5
"16",1.97500516666667,9.9946096666667,55.615333333333
"17",1.97499288333334,9.9946255833333,55.725
"18",1.97498116666667,9.9946405166667,55.766333333333
"19",1.97496823333333,9.9946565833333,55.781333333333
"20",1.97495426666667,9.9946739166667,56.014333333333

Find the exact coordinates of a contour on a surface and plot it manually in R plotly

I am drawing a surface plot and would like to "manually" draw a contour line using plotly. In the code below I:
simulate the data for drawing the surface plot
calculate the coordinates of the contour line at a specific z level using the contoureR package
draw the surface plot and contour line
# Load packages
library(plotly) # for interactive visualizations
library(contoureR) # for calculating contour coordinates
# Simulate the data for plotting
x <- y <- seq(from = 0, to = 100, by = 1)
z1 <- outer(X = x, Y = y, FUN = function(x, y) x^0.2 * y^0.3) # data for surface plot
# Obtain coordinates of contour for z = 5
z_level <- 5
r <- contourLines(x = x, y = y, z = z1, levels = z_level)
plot_ly(
type = "surface",
x = x,
y = y,
z = z1,
) %>%
add_trace(
type = "scatter3d",
x = r[[1]]$x,
y = r[[1]]$y,
z = z_level
)
I am aware that these are all approximations, so I also tried to pass the x and y coordinates produced by contourLines() to the formula used to create z1above and use the corresponding values to plot my contour line (instead of using z_level = 5, but I still do not obtain the desired result:
plot_ly(
x = x,
y = y,
z = z1,
type = "surface"
) %>%
add_trace(
type = "scatter3d",
x = r[[1]]$x,
y = r[[1]]$y,
z = r[[1]]$x^0.2*r[[1]]$y^0.3
)
I alo know that plotly enables me to draw specific contour lines (see my question and answer here: Add a permanent contour line to a surface plot in R plotly). However, I would like to draw my contour line myself (after getting their coordinates) so it can "pull" by cursor and show me the tooltip info whenever I hover over it. Ideally, if there was a way to obtain the contour lines coordinates as computed by plotly itself, that would be great.
Thank you for your help.
I was able to find two solutions to this problem.
Solution 1: transpose the z1 matrix
The first solution was given me by #nirgrahamuk and it consists in transposing the z1 matrix:
library(plotly) # for interactive visualizations
# Simulate the data for plotting
x <- y <- seq(from = 0, to = 100, by = 1)
z1 <- outer(X = x, Y = y, FUN = function(x, y) x^0.2 * y^0.3) # data for surface plot
# Obtain coordinates of contour for z = 5
z_level <- 6
r <- contourLines(x = x,
y = y,
z = z1,
levels = z_level)
plot_ly(
type = "surface",
z = t(z1), # *** WE TRANSPOSE THE MATRIX HERE! ***
) %>%
add_trace(
type = "scatter3d",
x = r[[1]]$x,
y = r[[1]]$y,
z = z_level
)
Solution 2: use the isoband package
The second solution is to compute the contour lines coordinates with the isoband::isolines() function:
library(plotly) # for interactive visualizations
library(isoband) # for find contour lines coordinates
# Simulate the data for plotting
x <- y <- seq(from = 0, to = 100, by = 1)
z1 <- outer(X = x, Y = y, FUN = function(x, y) x^0.2 * y^0.3) # data for surface plot
# Obtain coordinates of contour for z = 5
z_level <- 6
r <- isolines(x = x, # *** WE USE THE isolines() FUNCTION HERE ***
y = y,
z = z1,
levels = z_level)
plot_ly(
type = "surface",
z = z1,
) %>%
add_trace(
type = "scatter3d",
x = r[[1]]$x,
y = r[[1]]$y,
z = z_level
)

R plotly mesh3 coordinate lines through origin

I try to plot cube and ball around it in 3D using plotly in R, type = "mesh3D". I was successful to get the plots right, however, can't get the coordinate lines to go through the origin, point (0,0,0). Any suggestions on how to do that? Code example:
library(misc3d)
library(plotly)
grid <- 100
f.1 <- function(x, y, z){
(x^2+y^2+z^2)
}
f.2 <- function(x, y, z){
abs(x)+abs(y)+abs(z)
}
x <- seq(-1, 1, length=grid)
y <- seq(-1, 1, length=grid)
z <- seq(-1, 1, length=grid)
g <- expand.grid(x=x, y=y, z=z)
voxel.1 <- array(with(g, f.1(x,y,z)), c(grid,grid,grid))
voxel.2 <- array(with(g, f.2(x,y,z)), c(grid,grid,grid))
cont.1 <- computeContour3d(voxel.1, level=1, x=x, y=y, z=z)
idx.1 <- matrix(0:(nrow(cont.1)-1), ncol=3, byrow=TRUE)
cont.2 <- computeContour3d(voxel.2, level=1, x=x, y=y, z=z)
idx.2 <- matrix(0:(nrow(cont.2)-1), ncol=3, byrow=TRUE)
axx <- list(gridcolor="rgb(255,255,255)",zerolinecolor="rgb(0,0,0)")
axy <- list(gridcolor="rgb(255,255,255)",zerolinecolor="rgb(0,0,0)")
axz <- list(gridcolor="rgb(255,255,255)",zerolinecolor="rgb(0,0,0)")
plot.1 <- plot_ly(x = cont.1[,1], y = cont.1[,2], z = cont.1[,3],
i = idx.1[,1], j = idx.1[,2], k = idx.1[,3],
type = "mesh3d",opacity = 0.1,intensity=seq(0,1,length=4),showscale = FALSE,colors="red") %>%
add_trace(x = cont.2[,1], y = cont.2[,2], z = cont.2[,3],
i = idx.2[,1], j = idx.2[,2], k = idx.2[,3],color="blue",
type="mesh3d",opacity=0.7,intensity=seq(0,1,length=4),
showscale=FALSE,inherit=FALSE) %>%
layout(scene = list(xaxis=axx,yaxis=axy,zaxis=axz))
plot.1
It plots zerolines through (1,0,0), (0,1,0) and (0,0,1), but cant get it to plot through (0,0,0).

Plotly Contour plot behaviour

I want to understand how to correctly do contour plots with plotly. In the code below I have x,y,z so I interpolate to have a more defined range with the interp in akima package. I plot the result first with plotly then with filled.contour. The result of the plotly is wrong but I like more its aesthetics in the filled contour the results is correct.
What am I doing wrong with plotly?
require(akima)
require(plotly)
x = rand(15,1)
y = rand(15,1)
z = rand(15,1)
a = interp(x, y, z)
p = plot_ly(x = a$x,
y = a$y,
z = a$z,
type = "contour")
p
filled.contour(a$x,a$y,a$z)
Plotly expects a little bit different matrix arrangement. Here is a fix:
require(akima)
require(plotly)
library(pracma)
set.seed(1)
x = rand(15,1)
y = rand(15,1)
z = rand(15,1)
a = interp(x, y, z)
plot_ly(x = a$x,
y = a$y,
z = matrix(a$z, nrow = length(a$y), byrow = TRUE),
type = "contour")
filled.contour(a$x,a$y,a$z)
without the matrix rearrangement:
plot_ly(x = a$x,
y = a$y,
z = a$z,
type = "contour")

3D Biplot in plotly - R

I want to build a 3D PCA bi-plot using plotly package because the graph is nice and interactive in html format (something that I need).
My difficulty is to add the loading. I want the loading to be presented as straight lines from the point (0,0,0) (i.e. the equivalent to 2D biplots)
So all in all I don't know how to add straight lines starting from the centre of the 3D graph.
I have calculated the scores and loading using the PCA function;
pca1 <- PCA (dat1, graph = F)
for scores:
ind1 <- pca1$ind$coord[,1:3]
x <- ind1[,1] ; y <- ind1[,2] ; z <- ind1[,3]
for loadings:
var1 <- pca1$var$coord[,1:3]
xl <- var1[,1] ; yl <- var1[,2] ; zl <- var1[,3]
and using the code bellow the 3D score plot is generated;
p <- plot_ly( x=x, y=y, z=z,
marker = list(opacity = 0.7, color=y , colorscale = c('#FFE1A1', '#683531'), showscale = F)) %>%
layout(title = "3D Prefmap",
scene = list(
xaxis = list(title = "PC 1"),
yaxis = list(title = "PC 2"),
zaxis = list(title = "PC 3")))
Here are some ideas that could be useful for the development of a 3D biplot.
# Data generating process
library(MASS)
set.seed(6543)
n <- 500
mu <- c(1,-2,3,-1,3,4)
Sigma <- diag(rep(1,length(mu)))
Sigma[3,1] <- Sigma[1,3] <- 0.1
Sigma[4,6] <- Sigma[6,4] <- 0.1
X <- as.data.frame(mvrnorm(n, mu=mu, Sigma=Sigma))
# PCA
pca <- princomp(X, scores=T, cor=T)
# Scores
scores <- pca$scores
x <- scores[,1]
y <- scores[,2]
z <- scores[,3]
# Loadings
loads <- pca$loadings
# Scale factor for loadings
scale.loads <- 5
# 3D plot
library(plotly)
p <- plot_ly() %>%
add_trace(x=x, y=y, z=z,
type="scatter3d", mode="markers",
marker = list(color=y,
colorscale = c("#FFE1A1", "#683531"),
opacity = 0.7))
for (k in 1:nrow(loads)) {
x <- c(0, loads[k,1])*scale.loads
y <- c(0, loads[k,2])*scale.loads
z <- c(0, loads[k,3])*scale.loads
p <- p %>% add_trace(x=x, y=y, z=z,
type="scatter3d", mode="lines",
line = list(width=8),
opacity = 1)
}
print(p)

Resources