2

I am working with the R programming language.

In a previous question that I asked (Understanding 3D traces in Plotly and R: Evaluating and Plotting Functions Over a Grid), I learned how to plot mathematical functions by first evaluating the mathematical function at different points, then by plotting these points on a 3D grid, and finally "interpolating" a 3D surface over these points:

# set seed for reproducibility 
#load libraries
set.seed(123)
library(dplyr)
library(plotly)

#create more data
n <- 50
my_grid <- expand.grid(i1 = 1:n, i2 = 1:n)
my_grid$final_value = with(my_grid, sin(i1) + cos(i2) )

#make plot
plot_ly(data = my_grid,  x=~i1, y=~i2, z=~final_value, type='mesh3d', intensity = ~final_value, colors = colorRamp(c("blue", "grey", "red")))

enter image description here

I am trying to use this same approach to plot the following function (https://en.wikipedia.org/w/index.php?title=Test_functions_for_optimization&oldid=1030693803, https://en.wikipedia.org/w/index.php?title=Test_functions_for_optimization&oldid=1030693803#/media/File:ConstrTestFunc03.png) :

enter image description here

I first defined the function:

  my_function <- function(x,y) {
    
    final_value = (1 - x)^2 + 100*((y - x^2)^2)
     
    }

Then, I defined the "grid":

input_1 <- seq(-1.5, 1.5,0.1)
input_2 <- seq(-1.5, 1.5,0.1)


my_grid <- data.frame(input_1, input_2)
my_grid$final_value =   (1 - input_1)^2 + 100*((input_2 - input_1^2)^2)

Then, I tried to plot this function:

 x <- my_grid$input_1
y <- my_grid$input_2

z <- matrix(my_grid$final_value, nrow = length(x), ncol = length(y)) # proper matrix & dimensions

plot_ly(x = x, y = y, z = z) %>% add_surface()

My Problem: The final result does not look similar to the result from the Wikipedia page:

enter image description here

Can someone please show me what I am doing wrong? Is there an easier way to do this?

Thanks!

stats_noob
  • 5,401
  • 4
  • 27
  • 83

1 Answers1

3

Your problem is that you are not actually creating a grid, you are creating a single vector of equal x, y points and running your formula on that, so your matrix is wrong (every column will be the same due to it being repeated). The easiest fix is to run outer on your function to evaluate it at every pair of input 1 and input 2:

z <- outer(input_1, input_2, my_function)

plot_ly(x = input_1, y = input_2, z = z) %>% add_surface()

enter image description here

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87
  • Thank you so much for your answer! If you have time, could you please show me how to add "contours" to this plot? I tried the code below and it does not seem to be working: – stats_noob Mar 01 '22 at 18:21
  • fig <- plot_ly( type = 'surface', contours = list( x = list(show = TRUE, start = 1.5, end = 2, size = 0.04, color = 'white'), z = list(show = TRUE, start = 0.5, end = 0.8, size = 0.05)), x = ~input_1, y = ~input_2, z = ~z) fig <- fig %>% layout( scene = list( xaxis = list(nticks = 20), zaxis = list(nticks = 4), camera = list(eye = list(x = 0, y = -1, z = 0.5)), aspectratio = list(x = .9, y = .8, z = 0.2))) fig – stats_noob Mar 01 '22 at 18:21
  • I adapted the code from here: https://plotly.com/r/3d-surface-plots/ – stats_noob Mar 01 '22 at 18:21
  • I posted my progress over here: https://stackoverflow.com/questions/71313167/adding-contour-lines-to-3d-plots Thank you so much! – stats_noob Mar 01 '22 at 18:39