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

是否有R函数可为三维聚类绘制椭球(或其他包围图形)?

给三维聚类添加半透明包围椭球(基于plot_ly与iris数据集)

要给plot_ly生成的三维聚类图添加半透明椭球,核心思路是先计算每个聚类的统计特征(均值、协方差矩阵),再基于这些特征生成椭球的网格点,最后将椭球作为曲面层叠加到散点图上。以下是完整实现代码:

步骤1:加载依赖包

library(plotly)
library(dplyr)

步骤2:定义3D椭球生成函数

这个函数通过单位球变换生成对应聚类分布的椭球:

generate_ellipsoid <- function(mean_vec, cov_mat, n_points = 100, scale = 1) {
  # 生成单位球的球面点
  theta <- seq(0, 2*pi, length.out = n_points)
  phi <- seq(0, pi, length.out = n_points)
  x <- cos(theta) * sin(phi)
  y <- sin(theta) * sin(phi)
  z <- cos(phi)
  sphere <- cbind(x, y, z)
  
  # 用协方差矩阵的Cholesky分解将单位球映射为目标椭球
  chol_mat <- chol(cov_mat)
  ellipsoid <- t(chol_mat %*% t(sphere)) * scale + rep(mean_vec, each = n_points^2)
  
  # 整理为plot_ly兼容的数据框格式
  as.data.frame(ellipsoid) %>% rename(x = V1, y = V2, z = V3)
}

步骤3:计算聚类统计量并生成椭球数据

按Species分组计算每个聚类的均值和协方差,再生成对应椭球的坐标点:

# 分组计算每个物种的均值与协方差矩阵
cluster_stats <- iris %>%
  group_by(Species) %>%
  summarise(
    mean_sw = mean(Sepal.Width),
    mean_sl = mean(Sepal.Length),
    mean_pl = mean(Petal.Length),
    cov_mat = list(cbind(Sepal.Width, Sepal.Length, Petal.Length) %>% cov()),
    .groups = "drop"
  )

# 生成所有物种的椭球数据
ellipsoid_data <- lapply(1:nrow(cluster_stats), function(i) {
  mean_vec <- c(cluster_stats$mean_sw[i], cluster_stats$mean_sl[i], cluster_stats$mean_pl[i])
  generate_ellipsoid(mean_vec, cluster_stats$cov_mat[[i]], scale = 1.5) %>%
    mutate(Species = cluster_stats$Species[i])
}) %>% bind_rows()

步骤4:绘制带椭球的三维聚类图

先绘制基础散点图,再逐个添加对应物种的半透明椭球:

# 绘制基础散点图
p <- plot_ly(iris, x=~Sepal.Width, y=~Sepal.Length, z=~Petal.Length, 
             color = ~Species, type = "scatter3d", mode = "markers",
             marker = list(size = 4))

# 为每个物种添加半透明椭球
for (sp in unique(ellipsoid_data$Species)) {
  sp_ellipsoid <- filter(ellipsoid_data, Species == sp)
  # 匹配对应物种的颜色,设置半透明
  sp_color <- unique(iris$Species)[which(unique(iris$Species) == sp)]
  p <- add_surface(p, x=~x, y=~y, z=~z, data = sp_ellipsoid,
                   opacity = 0.2,
                   showlegend = FALSE,
                   colorscale = list(c(0, 1), c(sp_color, sp_color)))
}

# 展示图形
p

关键参数说明

  • scale:控制椭球的大小,设置为1.5时基本能覆盖聚类中大部分数据点,可根据需求调整
  • opacity:设置椭球的透明度,0.2既能突出聚类范围,又不会遮挡散点
  • showlegend = FALSE:避免椭球在图例中重复显示,保持图例简洁

如果需要其他包围方式(比如凸包),可以用convhulln函数(来自geometry包)生成凸包点,再用add_mesh添加到图中,但椭球更能直观体现聚类的正态分布特征。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 20:12:42