最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Solid of revolution around Y axis 3D plots in R - multiple plots with plotly - Stack Overflow

programmeradmin4浏览0评论

I am trying to plot 2 solids of revolution using plotly in R, and would like to obtain an image with both of the plots side by side. However, the plots seem to appear on top of each others instead.

I start creating a 3D scatter plot following the very useful example found in this answer.

In my case, I wanted to use a gaussian curve and rotate it around the Y axis, instead of X axis as in the example, so I modified the code as below:

#my test with gaussian

r <- function(x,sigma,mu) 1/(sqrt(2*pi)*sigma)*(exp(-1*(x-mu)^2/2/(sigma^2)))

#centre distribution on 0
mu=0

#choose a sigma
sigma=1

#interval of interest on the x
int <- c(-5, 5)

# number of points along the x-axis
nx <- 1000

# number of points along the rotation
ntheta <- 100

# set x points and get corresponding radii = calculates the value of the function for all x points
coords <- data_frame(x = seq(int[1], int[2], length.out = nx), r = r(x, sigma, mu))

# for each r: rotate x to get xi and z coordinates
# edit: ensure 0 and pi are both amongst the angles used
coords %<>%
  rowwise() %>%
  do(data_frame(r = .$r, x = .$x,
                theta = seq(0, pi, length.out = ntheta / 2 + 1) %>%
                  c(pi + .[-c(1, length(.))]))) %>%
  
  ungroup %>%
  mutate(xi = x * sin(theta), z = x * cos(theta))

# plot points to make sure the coordinates define the desired shape
coords %>%
  plot_ly(x = ~xi, y = ~r, z = ~z, color = ~r)

#make a clean data frame with the things I need to plot so I don't get confused
X <- coords$xi
Y <- coords$r
Z <- coords$z

df1 <- data.frame(X, Y, Z)
head(df1)

#create the 3D plot with plotly

figsigma1 <- plot_ly(df1,
        type = 'scatter3d',
        mode='markers',
        x = ~X, 
        y = ~Y,
        z = ~Z,
        marker = list(
          color= ~Y,
          colorscale = "Viridis",
          cmax = 0.4,
          cmin = 0,
          colorbar=list(
            title='Intensity (AU)'
          ),
          reversescale =F
        )
)

figsigma1




#now everything is repeated to create another plot where the function has sigma=2

r <- function(x,sigma,mu) 1/(sqrt(2*pi)*sigma)*(exp(-1*(x-mu)^2/2/(sigma^2)))

#centre distribution on 0
mu=0

#choose a sigma
sigma=2

#interval of interest on the x
int <- c(-5, 5)

# number of points along the x-axis
nx <- 1000

# number of points along the rotation
ntheta <- 100

# set x points and get corresponding radii = calculates the value of the function for all x points
coords <- data_frame(x = seq(int[1], int[2], length.out = nx), r = r(x, sigma, mu))

# for each r: rotate x to get xi and z coordinates
# edit: ensure 0 and pi are both amongst the angles used
coords %<>%
  rowwise() %>%
  do(data_frame(r = .$r, x = .$x,
                theta = seq(0, pi, length.out = ntheta / 2 + 1) %>%
                  c(pi + .[-c(1, length(.))]))) %>%
  
  ungroup %>%
  mutate(xi = x * sin(theta), z = x * cos(theta))

# plot points to make sure the coordinates define the desired shape
coords %>%
  plot_ly(x = ~xi, y = ~r, z = ~z, color = ~r)

#make a clean data frame with the things I need to plot so I don't get confused
X <- coords$xi
Y <- coords$r
Z <- coords$z

df2 <- data.frame(X, Y, Z)
head(df2)

figsigma2 <- plot_ly(df2,
                     type = 'scatter3d',
                     mode='markers',
                     x = ~X, 
                     y = ~Y,
                     z = ~Z,
                     marker = list(
                       color= ~Y,
                       colorscale = "Viridis",
                       cmax = 0.4,
                       cmin = 0,
                       colorbar=list(
                         title='Intensity (AU)'
                       ),
                       reversescale =F
                     )
)

figsigma2

This gives me the plots I wanted

At this point I wanted to have the two plots side by side, so I tried the below:


main_plot <- subplot(figsigma1, figsigma2)
main_plot

However, this seems to plot them on top of each other instead of side by side... any suggestion?

I am trying to plot 2 solids of revolution using plotly in R, and would like to obtain an image with both of the plots side by side. However, the plots seem to appear on top of each others instead.

I start creating a 3D scatter plot following the very useful example found in this answer.

In my case, I wanted to use a gaussian curve and rotate it around the Y axis, instead of X axis as in the example, so I modified the code as below:

#my test with gaussian

r <- function(x,sigma,mu) 1/(sqrt(2*pi)*sigma)*(exp(-1*(x-mu)^2/2/(sigma^2)))

#centre distribution on 0
mu=0

#choose a sigma
sigma=1

#interval of interest on the x
int <- c(-5, 5)

# number of points along the x-axis
nx <- 1000

# number of points along the rotation
ntheta <- 100

# set x points and get corresponding radii = calculates the value of the function for all x points
coords <- data_frame(x = seq(int[1], int[2], length.out = nx), r = r(x, sigma, mu))

# for each r: rotate x to get xi and z coordinates
# edit: ensure 0 and pi are both amongst the angles used
coords %<>%
  rowwise() %>%
  do(data_frame(r = .$r, x = .$x,
                theta = seq(0, pi, length.out = ntheta / 2 + 1) %>%
                  c(pi + .[-c(1, length(.))]))) %>%
  
  ungroup %>%
  mutate(xi = x * sin(theta), z = x * cos(theta))

# plot points to make sure the coordinates define the desired shape
coords %>%
  plot_ly(x = ~xi, y = ~r, z = ~z, color = ~r)

#make a clean data frame with the things I need to plot so I don't get confused
X <- coords$xi
Y <- coords$r
Z <- coords$z

df1 <- data.frame(X, Y, Z)
head(df1)

#create the 3D plot with plotly

figsigma1 <- plot_ly(df1,
        type = 'scatter3d',
        mode='markers',
        x = ~X, 
        y = ~Y,
        z = ~Z,
        marker = list(
          color= ~Y,
          colorscale = "Viridis",
          cmax = 0.4,
          cmin = 0,
          colorbar=list(
            title='Intensity (AU)'
          ),
          reversescale =F
        )
)

figsigma1




#now everything is repeated to create another plot where the function has sigma=2

r <- function(x,sigma,mu) 1/(sqrt(2*pi)*sigma)*(exp(-1*(x-mu)^2/2/(sigma^2)))

#centre distribution on 0
mu=0

#choose a sigma
sigma=2

#interval of interest on the x
int <- c(-5, 5)

# number of points along the x-axis
nx <- 1000

# number of points along the rotation
ntheta <- 100

# set x points and get corresponding radii = calculates the value of the function for all x points
coords <- data_frame(x = seq(int[1], int[2], length.out = nx), r = r(x, sigma, mu))

# for each r: rotate x to get xi and z coordinates
# edit: ensure 0 and pi are both amongst the angles used
coords %<>%
  rowwise() %>%
  do(data_frame(r = .$r, x = .$x,
                theta = seq(0, pi, length.out = ntheta / 2 + 1) %>%
                  c(pi + .[-c(1, length(.))]))) %>%
  
  ungroup %>%
  mutate(xi = x * sin(theta), z = x * cos(theta))

# plot points to make sure the coordinates define the desired shape
coords %>%
  plot_ly(x = ~xi, y = ~r, z = ~z, color = ~r)

#make a clean data frame with the things I need to plot so I don't get confused
X <- coords$xi
Y <- coords$r
Z <- coords$z

df2 <- data.frame(X, Y, Z)
head(df2)

figsigma2 <- plot_ly(df2,
                     type = 'scatter3d',
                     mode='markers',
                     x = ~X, 
                     y = ~Y,
                     z = ~Z,
                     marker = list(
                       color= ~Y,
                       colorscale = "Viridis",
                       cmax = 0.4,
                       cmin = 0,
                       colorbar=list(
                         title='Intensity (AU)'
                       ),
                       reversescale =F
                     )
)

figsigma2

This gives me the plots I wanted

At this point I wanted to have the two plots side by side, so I tried the below:


main_plot <- subplot(figsigma1, figsigma2)
main_plot

However, this seems to plot them on top of each other instead of side by side... any suggestion?

Share Improve this question asked Mar 26 at 11:36 Annalisa BellandiAnnalisa Bellandi 275 bronze badges 2
  • 1 library(htmltools); browsable(div(style = "display: flex; flex-wrap: wrap; justify-content: center", div(figsigma1, style = "width: 50%;"), div(figsigma2, style = "width: 50%;"))) should do it - as described here. This is similar to this post. Also funny shape ;) – Tim G Commented Mar 26 at 11:57
  • 1 Another solution would install.packages("manipulateWidget"); manipulateWidget::combineWidgets(figsigma1, figsigma2, nrow = 1) as per this – Tim G Commented Mar 26 at 12:12
Add a comment  | 

1 Answer 1

Reset to default 1

You can do

library(htmltools)
browsable(
  div(style = "display: flex; flex-wrap: wrap; justify-content: center", 
    div(figsigma1, style = "width: 50%;"), 
    div(figsigma2, style = "width: 50%;")
  )
)

as described here - it's more flexible if you know your css.

Or a bit more concise

install.packages("manipulateWidget") 
manipulateWidget::combineWidgets(figsigma1, figsigma2, nrow = 1)

as per this great answer.

发布评论

评论列表(0)

  1. 暂无评论