R: Plot_ly 3d graph with trace line - r

I am using plotly 4.7.0. I am trying to add a 3d line to a 3d plot_ly surface plot. When I don't add the add_lines() function inside of the plot_ly call it looks fine. As soon as I do add the add_lines, the graph gets all messed up and doesn't add the 3d line graph.
library(plotly)
m_x = seq(-2, 2, .01)
m_y = seq(-2, 2, .01)
df = expand.grid(m_x, m_y)
df['matrix'] = exp(-(df$Var1^2+df$Var2^2))
m_z = matrix(df$matrix, nrow = length(m_x), ncol = length(m_y))
m_df = list(m_x, m_y, m_z)
x1 = seq(-2, 0, by=0.0202)
y1 = runif(100, min=-0.03,max=0.03)
z1 = exp(-(x1^2+y1^2))
df = data.frame(x1, y2, z2)
names(df) <- c("df_x", "df_y", "df_z")
colors = c( "Blue", "Cyan", "Green", "Yellow", "Orange", "Red")
p1 <- plot_ly(x = m_df[[1]], y = m_df[[2]], z = m_df[[3]],
colors = colors, color = m_df[[3]]) %>% add_surface() %>%
add_lines(x = df$df_x, y = df$df_y, z = df$df_z, data = df,
line = list(color = 'red', width = 1)) %>%
layout(title = "Hike_Example",
scene = list(aspectratio = list(x = 4, y = 4, z = 1)))
p1

Here is the code of the surface plot with the 3D line.
I plotted the 3D line using add_trace in place of add_lines.
library(plotly)
m_x = seq(-2, 2, .01)
m_y = seq(-2, 2, .01)
df = expand.grid(m_x, m_y)
df['matrix'] = exp(-(df$Var1^2+df$Var2^2))
m_z = matrix(df$matrix, nrow = length(m_x), ncol = length(m_y))
m_df = list(m_x, m_y, m_z)
x1 = seq(-2, 0, by=0.0202)
y1 = runif(100, min=-0.03,max=0.03)
z1 = exp(-(x1^2+y1^2))
df = data.frame(x1, y1, z1)
names(df) <- c("df_x", "df_y", "df_z")
colors = c( "Blue", "Cyan", "Green", "Yellow", "Orange", "Red")
p1 <- plot_ly(x = m_df[[1]], y = m_df[[2]], z = m_df[[3]],
colors = colors, color = m_df[[3]]) %>% add_surface() %>%
add_trace(x = ~df_x, y = ~df_y, z = ~df_z, data = df,
type="scatter3d", mode="lines",
line = list(color = "red", width = 4)) %>%
layout(title = "Hike_Example",
scene = list(aspectratio = list(x = 4, y = 4, z = 1)))
p1

Related

How to change colors and symbols according to categorical variable in R plotly:::add_markers()?

I am trying to change markers' colors and symbols according to a categorical variable in r-plotly. But it is not working. Also, I would like to draw "contour lines" around the "walls" of the 3d panel, similar to what I have in the attached figure. Any help is welcome.
# Packages
library(plotly)
library(misc3d)
# Fake data
norm_vec <- function(x) sqrt(sum(x ^ 2))
X3d_norm <- data.frame(T3 = runif(100), T6 = runif(100), P4 = runif(100))
norms <- apply(X3d_norm, 1, norm_vec)
X3d_norm <- X3d_norm / norms
X3d_norm$cluster <- factor(sample(1:2, 100, replace = T), ordered = T)
# Getting octant data
f <- function(x, y, z){x ^ 2 + y ^ 2 + z ^ 2}
R <- 1
x <- y <- z <- seq(0, R, length.out = 100)
g <- expand.grid(x = x, y = y, z = z)
voxel <- array(with(g, f(x, y, z)),dim = c(100, 100, 100))
cont <- computeContour3d(voxel, level = R ^ 2, x = x, y = y, z = z)
idx <- matrix(0:(nrow(cont) - 1), ncol = 3,byrow = TRUE)
# Colors and symbols
pal <- c("#E69F00", "#009E73")
pal <- setNames(pal, c(1, 2))
symb <- c("circle", "square")
symb <- setNames(symb, c(1, 2))
# Plot
plot_ly() %>%
add_mesh(
x = cont[, 1], y = cont[, 2], z = cont[, 3],
i = idx[, 1], j = idx[, 2], k = idx[, 3],
opacity = 0.15
) %>%
add_markers(
data = X3d_norm,
x = ~T3, y = ~P4, z = ~T6,
color = ~cluster, colors = pal,
symbol = ~cluster, symbols = symb
) %>%
layout(
legend = list(title = list(text = 'Clusters')),
scene = list(
xaxis = list(
title = "T3", nticks = 4, tickvals = c(0.20, 0.40, 0.60, 0.80),
tickfont = list(size = 16), titlefont = list(size = 24)),
yaxis = list(
title = "P4", nticks = 4, tickvals = c(0.20, 0.40, 0.60, 0.80),
tickfont = list(size = 16), titlefont = list(size = 24)),
zaxis = list(
title = "T6", nticks = 4, tickvals = c(0.20, 0.40, 0.60, 0.80),
tickfont = list(size = 16), titlefont = list(size = 24))
)
)

How to manually add symbols with plotly in R

I have a plot_ly 3D scatter plot that uses three traces, and I want to use a different symbol and color for each trace. My code looks like this
library(plotrix)
library(plotly)
library(processx)
x <- c(1, 2, 3, 4)
y <- c(2, 4, 6, 8)
z <- c(1, 2, 3, 4)
df <- data.frame(x, y, z)
z1 <- z + 1.5
df1 <- data.frame(x, y, z1)
z2 <- z + 3
df2 <- data.frame(x, y, z2)
symbols <- c("circle", "diamond", 'triangle-down')
colors <- c("gray", "lightgray", "darkslategray")
plot<- plot_ly()%>%
add_trace(data = df, x = ~x, y = ~y, z = ~z,type = "scatter3d",
mode = 'markers', marker = list(size = 8, symbol = 1, symbols = symbols, color = 1, colors = colors)) %>%
add_trace(data = df1, x = ~x, y = ~y, z = ~z1,type = "scatter3d",
mode = 'markers', marker = list(size = 8, symbol = 2, symbols = symbols, color = 2, colors = colors)) %>%
add_trace(data = df2, x = ~x, y = ~y, z = ~z2,type = "scatter3d",
mode = 'markers', marker = list(size = 8, symbol = 8, symbols = symbols, color = 3, colors = colors)) %>%
layout(title = 'Explore Options')
plot
which I would like to have the first trace to use circle markers, the second diamond and the third triangles, each with a different gray scale color, but instead I just get colored circles i.e.
One option would be to add a column to your dataframes which could then be mapped on the color and symbol attributes. Additionally I use named vectors of colors and symbols to assign colors and symbols to categories of the new column. Also note that colors and symbols should not to be placed inside the list for the marker specifications. Finally I simplified your code a bit.
The "triangle-down" symbol does not work, according to this reference, only ( "circle" | "circle-open" | "cross" | "diamond" | "diamond-open" | "square" | "square-open" | "x" ) are accepted.
library(plotly)
x <- c(1, 2, 3, 4)
y <- c(2, 4, 6, 8)
z <- c(1, 2, 3, 4)
df <- data.frame(x, y, z)
z1 <- z + 1.5
df1 <- data.frame(x, y, z = z1)
z2 <- z + 3
df2 <- data.frame(x, y, z = z2)
df$color <- "a"
df1$color <- "b"
df2$color <- "c"
symbols <- c("circle", "diamond", 'square')
colors <- c("gray", "lightgray", "darkslategray")
names(colors) <- names(symbols) <- c("a", "b", "c")
plot<- plot_ly(x = ~x, y = ~y, z = ~z, color = ~color, symbol = ~color, colors = colors, symbols = symbols, marker = list(size = 8)) %>%
add_trace(data = df, type = "scatter3d", mode = 'markers') %>%
add_trace(data = df1, type = "scatter3d", mode = 'markers') %>%
add_trace(data = df2, type = "scatter3d", mode = 'markers') %>%
layout(title = 'Explore Options')
plot

How to do 3D line plots grouped by two factors with the Plotly package in R?

I have checked up the official webpage of Plotly, but how to plot the following task still escapes me:
id <- c(rep(1,5), rep(2,5), rep(3,5), rep(4,5))
t <- rep(seq(50,75,length.out=5), 4)
x <- runif(20) + sin(t)
y <- rnorm(20) + cos(t)
gender <- c(rep("F",10), rep("M",10))
smoke <- c(rep("Y",5), rep("N",10), rep("Y",5))
DATA <- data.frame(ID, t, x, y, gender, smoke)
fig <- plot_ly(DATA, x = ~t, y = ~y, z = ~x, .......)
Suppose I have 4 groups of patients (grouped by 2 factors, Female/Male and Smokers/Non-smokers), each associated with 5 observations $(x_i, y_i)$ along the timestamps $t_i$. So I need to draw a 3D line plot $${(t_i, x_i, y_i)}_{i=1}^{i=5}$ for each patient, but all in one plotting canvas. If I want to represent genders by red/blue, smokers by solid and non-smokers by dash lines, and specify these in the legend, what should I do (ideally using R)?
The kind of 3D plot you have in mind can be achievd like so:
library(plotly)
id <- c(rep(1,5), rep(2,5), rep(3,5), rep(4,5))
t <- rep(seq(50,75,length.out=5), 4)
x <- runif(20) + sin(t)
y <- rnorm(20) + cos(t)
gender <- c(rep("F",10), rep("M",10))
smoke <- c(rep("Y",5), rep("N",10), rep("Y",5))
DATA <- data.frame(id, t, x, y, gender, smoke)
col_gender <- c(M = "red", F = "blue")
lt_smoke <- c(Y = "solid", N = "dash")
sym_id <- c(`1` = "circle", `2` = "square", `3` = "diamond", `4` = "cross")
fig <- plot_ly(DATA,
x = ~x, y = ~y, z = ~t, symbol = ~id, color = ~gender, linetype = ~smoke, type = 'scatter3d', mode = 'lines+markers',
line = list(width = 6),
marker = list(size = 3.5, cmin = -20, cmax = 50),
colors = col_gender,
linetypes = lt_smoke,
symbols = sym_id)
fig
Edit:
In case of more patients the best option is to map id on color and additonally group by id using transform groupby
library(plotly)
id <- c(rep(1,5), rep(2,5), rep(3,5), rep(4,5), rep(5,5), rep(6,5), rep(7,5), rep(8,5))
t <- rep(seq(50,75,length.out=5), 8)
x <- runif(40) + sin(t)
y <- rnorm(40) + cos(t)
gender <- c(rep("F",10), rep("M",10), rep("F",10), rep("M",10))
smoke <- c(rep("Y",5), rep("N",10), rep("Y",5), rep("Y",5), rep("N",10), rep("Y",5))
lt_smoke <- c(Y = "solid", N = "dash")
sym_id <- c(M = "circle", F = "square")
fig <- plot_ly(DATA,
x = ~x, y = ~y, z = ~t, symbol = ~gender, color = ~id, linetype = ~smoke, type = 'scatter3d', mode = 'lines+markers',
line = list(width = 6),
marker = list(size = 3.5, cmin = -20, cmax = 50),
linetypes = lt_smoke,
symbols = sym_id,
transforms = list(
list(
type = 'groupby',
groups = ~id)
))
fig

R ggplotly() and colour annotations - How do you do it?

I am trying to replicate a plot from ggplot with the added functionality from Plotly with hover points, but it strips the annotations out and have tried everything to achieve the same view with no success .
library("ggplot2")
library("plotly")
test_data <- data.frame(A = c(1,5,7,4,2),
B = c(3,3,6,8,4))
my_days <- as.Date(c("2010-01-01", "2010-02-01",
"2010-03-01", "2010- 4-01",
"2010-05-01"))
df <- data.frame(test_data, my_days)
# Anotate Box
s_1 <- unique(min(df$my_days))
s_2 <- unique(max(df$my_days))
target <- 1
plot_out <- df %>%
group_by(my_days) %>%
summarise(prop = sum(A / B)) %>%
ggplot(aes(x =my_days, y = prop)) +
geom_line(color = "purple") +
annotate("rect", xmin = s_1, xmax = s_2, ymin = -Inf, ymax = target, alpha = .2, fill = "red") +
annotate("rect", xmin = s_1, xmax = s_2, ymin = target, ymax = Inf, alpha = .2, fill = "green")
plot_out # Plot with Colour
ggplotly(plot_out) # This gives the hover info points , but removes the annotates
Not a ggplotly solution but a plotly solution. (; At least in my opinion ggplotly is nice if you want to make a quick interactive version of a ggplot. However, ggplotly still has a lot of issues and is not able to convert every ggplot. Try this:
library("ggplot2")
library("plotly")
test_data <- data.frame(
A = c(1, 5, 7, 4, 2),
B = c(3, 3, 6, 8, 4)
)
my_days <- as.Date(c(
"2010-01-01", "2010-02-01",
"2010-03-01", "2010- 4-01",
"2010-05-01"
))
df <- data.frame(test_data, my_days)
# Anotate Box
s_1 <- unique(min(df$my_days))
s_2 <- unique(max(df$my_days))
target <- 1
p <- df %>%
group_by(my_days) %>%
summarise(prop = sum(A / B)) %>%
plot_ly(x = ~my_days, y = ~prop) %>%
add_lines(
line = list(color = "purple"),
hoverinfo = "text",
text = ~ paste0(
"mydays: ", my_days,
"\n", "prop: ", round(prop, 7)
)) %>%
# Add the rectangles and set x-axis as in ggplot
layout(
xaxis = list(
type = "date",
tickformat = "%b",
nticks = 5
),
shapes = list(
list(
type = "rect",
fillcolor = "red", opacity = 0.2,
x0 = s_1, x1 = s_2, xref = "x",
y0 = -Inf, y1 = target, yref = "y"
),
list(
type = "rect",
fillcolor = "green", opacity = 0.2,
x0 = s_1, x1 = s_2, xref = "x",
# Setting y1 to Inf results in a yaxis which spans up to 2.5. So I chose 1.8 to mimic the ggplot
y0 = target, y1 = 1.8, yref = "y"
)
)
)
p
Created on 2020-04-05 by the reprex package (v0.3.0)

how to plot lines in 3d graph in R

I have these two 3d graphs made in R, with two different functions:
x <- c(0,50,100,150,200,250,300,350,400,450)
y <- c(0,50,100,150,200,250,300,350,400,450)
z <- c(1,2,1,1,2,1,2,1,2,1)
plot_ly(x=x,y=y,z=z)
scatterplot3d(x, y, z)
I would like to plot in these two graphs, the following lines and the intersection area between them:
Lines plotted in both graphs
As per the lines and intersection with plotly, something like this will do:
library(scatterplot3d)
library(plotly)
x <- c(0,50,100,150,200,250,300,350,400,450)
y <- c(0,50,100,150,200,250,300,350,400,450)
z <- c(1,2,1,1,2,1,2,1,2,1)
data <- data.frame(x=x,y=y,z=z)
line <- data.frame(x = rep(200,5), y = seq(0,500,length.out = 5), z = rep(1,5))
line2 <- data.frame(x = rep(300,5), y = seq(0,500,length.out = 5), z = rep(1,5))
rect <- data.frame(expand.grid(x= c(200,300), y =c(200,300)),z = rep(1,4) )
plot_ly() %>%
add_trace(data=data, x=x, y=y, z=z, type="scatter3d", mode="markers") %>%
add_trace(line, x = line$x, y = line$y, z = line$z, type = 'scatter3d', mode = 'lines', line = list(color = 'rgb(1, 1, 1)', width = 1 , dash = 'dash', width = 4)) %>%
add_trace(line2, x = line2$x, y = line2$y, z = line2$z, type = 'scatter3d', mode = 'lines', line = list(color = 'rgb(1, 1, 1)', width = 1, dash = 'dash', width = 4)) %>%
add_trace(line, x = line$y, y = line$x, z = line$z, type = 'scatter3d', mode = 'lines', line = list(color = 'rgb(1, 1, 1)', width = 1 , dash = 'dash', width = 4)) %>%
add_trace(line2, x = line2$y, y = line2$x, z = line2$z, type = 'scatter3d', mode = 'lines', line = list(color = 'rgb(1, 1, 1)', width = 1, dash = 'dash', width = 4))%>%
add_trace(rect, x=rect$x, y=rect$y, z=rect$z, type="mesh3d" )
Result with plotly:

Resources