Plotly Contour plot behaviour - r

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")

Related

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

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.)

Error in identify(x, y, labels = name, plot = TRUE)

I trying to use the function identify() on R, but it's not working.
Do you know if there is any package that I'm missing?
It doesn't work not even for a simple code:
x = 1:10
y = x^2
name = letters[1:10]
plot(x, y)
identify(x, y, labels = name, plot=TRUE, n = 2)
This way it works: it is the same code: With n=2 you have to click on two points:
x = 1:10
y = x^2
name = letters[1:10]
plot(x, y)
identify(x, y, labels = name, plot=TRUE, n = 2)

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
)

Argument is missing while trying to add surface (R)

I am trying to run these functions to establish a 3D plot and I want to add a plane but an error occurs.
plot_ly(data = df, z = ~PM, x = ~Wind_speed, y = ~SO2, opacity = 0.5) %>%
add_markers()
x <- seq(370, 15000, by = 10)
y <- seq(0, 15000, by = 10)
plane <- outer(x, y, function(a, b){fit$coef[1] +
fit$coef[2]*a + fit$coef[3]*b})
add_surface(x = ~x, y = ~y, z = ~plane, showscale = FALSE)
but then this error shows up
> add_surface(x = ~x, y = ~y, z = ~plane, showscale = FALSE)
Error in add_trace_classed(p, class = "plotly_surface", z = z, type = "surface", :
argument "p" is missing, with no default
What should I do to fix this?
I do not know how it got solved but I could fix it somehow. I just reloaded the data, changed the order of the functions and wrote these functions together:
x <- seq(370, 15000, by = 10)
y <- seq(0, 15000, by = 10)
plane <- outer(x, y, function(a, b){fit$coef[1] +
fit$coef[2]*a + fit$coef[3]*b})
plot_ly(data = df, z = ~PM, x = ~Wind_speed, y = ~SO2, opacity = 0.5) %>%
add_markers()
add_surface(x = ~x, y = ~y, z = ~plane, showscale = FALSE)

3D Data with ggplot

I have data in the following form:
x <- seq(from = 0.01,to = 1, by = 0.01)
y <- seq(from = 0.01,to = 1, by = 0.01)
xAxis <- x/(1+x*y)
yAxis <- x/(1+x*y)
z <- (0.9-xAxis)^2 + (0.5-yAxis)^2
df <- expand.grid(x,y)
xAxis <- df$Var1/(1+df$Var1*df$Var2)
yAxis <- df$Var2/(1+df$Var1*df$Var2)
df$x <- xAxis
df$y <- yAxis
df$z <- z
I would like to plot te (x,y,z) data as a surface and contour plots, possibily interpolating data to obtain as smooth a figure as possible.
Searching I reached the akima package which does the interpolation:
im <- with(df,interp(x,y,z))
I am having trouble plotting the data with this output. Ideally I would like to use ggplot2 since I want to add stuff to the original plot.
Thanks!
I'm a bit puzzled as to what you are looking for, but how about something like this?
im <- with(df, akima::interp(x, y, z, nx = 1000, ny = 1000))
df2 <- data.frame(expand.grid(x = im$x, y = im$y), z = c(im$z))
ggplot(df2, aes(x, y, fill = z)) +
geom_raster() +
viridis::scale_fill_viridis()
For contour plots, I use the "rgl" package. This allows real-time manipulation of the plot in order to have the best view.
library("rgl")
x <- seq(from = 0.01,to = 1, by = 0.01)
y <- seq(from = 0.01,to = 1, by = 0.01)
#z <- (0.9-xAxis)^2 + (0.5-yAxis)^2
df <- expand.grid(x,y)
xAxis <- df$Var1/(1+df$Var1*df$Var2)
yAxis <- df$Var2/(1+df$Var1*df$Var2)
df$z <- (0.9-xAxis)^2 + (0.5-yAxis)^2
surface3d(x=x, y=y, z=df$z, col="blue", back="lines")
title3d(xlab="x", zlab="z", ylab="y")
axes3d(tick="FALSE")
The rgl package is comparable to the ggplot2 package to customize the final plot. The 0.01 grid spacing is more than close enough for this type of smooth surface.

Resources