You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中将多个3D曲面图展示在同一页面?

问题描述

我写了一段R代码,用来生成变量p3取不同值时的3D曲面图,代码及遇到的问题如下:

定义核心函数

library(plotly)
library(dplyr)

calculate_b_values <- function(p1, p2, p3, weights) {
  grid <- expand.grid(p1 = p1, p2 = p2)
  grid$B <- (weights$w4 / weights$w2) * weights$w3 * grid$p1 * grid$p2 * p3
  matrix(grid$B, nrow = length(p1), ncol = length(p2))
}

create_surface_plot <- function(p1, p2, z_matrix, p3_value) {
  plot_ly() %>% 
    add_surface(
      z = z_matrix,
      x = p1,
      y = p2,
      colorscale = "Viridis",
      opacity = 0.9
    ) %>% 
    layout(
      scene = list(
        xaxis = list(title = "p1"),
        yaxis = list(title = "p2"),
        zaxis = list(title = "B"),
        aspectratio = list(x = 1, y = 1, z = 0.7)
      ),
      title = paste("Surface Plot with p3 =", p3_value)
    )
}

generate_surface_plots <- function(p_range = seq(0.1, 1, length.out = 20),
                                  p3_values = c(0.1, 0.4, 0.7, 1.0),
                                  weights = list(w1 = 10, w2 = 5, w3 = 3, w4 = 8)) {
  plot_list <- list()
  for (i in seq_along(p3_values)) {
    p3_fixed <- p3_values[i]
    z_matrix <- calculate_b_values(p_range, p_range, p3_fixed, weights)
    plot_list[[i]] <- create_surface_plot(p_range, p_range, z_matrix, p3_fixed)
  }
  names(plot_list) <- paste0("p3_", p3_values)
  return(plot_list)
}

生成单个图表

weights <- list(w1 = 10, w2 = 5, w3 = 3, w4 = 8)
p_vals <- seq(0.1, 1, length.out = 20)
p3_values <- c(0.1, 0.4, 0.7, 1.0)

plots <- generate_surface_plots(p_vals, p3_values, weights)

plots[[1]]
plots[[2]]
plots[[3]]
plots[[4]]

合并图表失败尝试

我想用subplot将4个图表放在同一页面,代码如下:

plots <- generate_surface_plots(p_vals, p3_values, weights)

combined_plot <- subplot(
  plots[[1]], plots[[2]],
  plots[[3]], plots[[4]],
  nrows = 2, 
  titleX = TRUE,
  titleY = TRUE,
  margin = 0.05
)

combined_plot <- combined_plot %>%
  layout(
    title = list(
      text = "Surface Plots at Different p3 Values",
      font = list(size = 16)
    )
  )

combined_plot

但运行后所有图表叠加在同一个绘图区域,我需要实现4个独立3D图分2行2列排列的布局,类似Python的3D子图效果。


解决方案

问题根源是所有3D图默认共用同一个scene对象,导致叠加。需给每个子图分配唯一的scene标识,并在整体布局中指定每个scene的位置。

修改后的完整代码如下:

1. 更新绘图函数

新增scene_name参数,为每个图绑定独立的scene:

create_surface_plot <- function(p1, p2, z_matrix, p3_value, scene_name = "scene") {
  plot_ly() %>% 
    add_surface(
      z = z_matrix,
      x = p1,
      y = p2,
      colorscale = "Viridis",
      opacity = 0.9
    ) %>% 
    layout(
      !!scene_name := list(
        xaxis = list(title = "p1"),
        yaxis = list(title = "p2"),
        zaxis = list(title = "B"),
        aspectratio = list(x = 1, y = 1, z = 0.7)
      )
    )
}

2. 更新批量生成函数

为每个图指定唯一的scene名称:

generate_surface_plots <- function(p_range = seq(0.1, 1, length.out = 20),
                                  p3_values = c(0.1, 0.4, 0.7, 1.0),
                                  weights = list(w1 = 10, w2 = 5, w3 = 3, w4 = 8)) {
  plot_list <- list()
  scene_names <- paste0("scene", seq_along(p3_values))
  for (i in seq_along(p3_values)) {
    p3_fixed <- p3_values[i]
    z_matrix <- calculate_b_values(p_range, p_range, p3_fixed, weights)
    plot_list[[i]] <- create_surface_plot(p_range, p_range, z_matrix, p3_fixed, scene_names[i])
  }
  names(plot_list) <- paste0("p3_", p3_values)
  return(plot_list)
}

3. 合并并布局子图

通过domain参数指定每个scene在画布上的位置,实现2行2列排列:

plots <- generate_surface_plots(p_vals, p3_values, weights)

combined_plot <- subplot(
  plots[[1]], plots[[2]],
  plots[[3]], plots[[4]],
  nrows = 2,
  shareX = FALSE, shareY = FALSE,
  margin = 0.1
) %>%
  layout(
    title = list(text = "Surface Plots at Different p3 Values", font = list(size = 16)),
    scene1 = list(domain = list(x = c(0, 0.45), y = c(0.55, 1))),
    scene2 = list(domain = list(x = c(0.55, 1), y = c(0.55, 1))),
    scene3 = list(domain = list(x = c(0, 0.45), y = c(0, 0.45))),
    scene4 = list(domain = list(x = c(0.55, 1), y = c(0, 0.45)))
  )

combined_plot

关键说明

  • 每个3D图必须绑定唯一的scene对象,避免共用导致叠加;
  • domain参数用0-1的比例值指定每个scene在画布上的坐标范围,实现2行2列的排列;
  • 设置shareX = FALSE, shareY = FALSE保证每个子图的坐标轴独立。

内容的提问来源于stack exchange,提问作者stats_noob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 00:19:50