☰
ggplot2 与 gghalves 绘制云雨图:3步组合核密度、箱线与散点
2026/10/25 9:20:41 网站建设 项目流程

ggplot2 与 gghalves 绘制云雨图:3步组合核密度、箱线与散点

在数据分析的可视化领域,云雨图(Raincloud Plot)正逐渐成为展示数据分布特征的首选工具。这种创新的图表类型将核密度估计、箱线图和散点图三者巧妙融合,既能呈现数据的整体分布形态,又能保留每个数据点的具体信息。本文将深入探讨如何利用R语言中的ggplot2和gghalves包,通过三个核心步骤构建专业级的云雨图,并分享一系列提升图表表现力的进阶技巧。

1. 环境准备与数据理解

在开始绘制之前,我们需要确保工作环境配置正确。R语言的强大之处在于其丰富的扩展包生态系统,对于云雨图而言,ggplot2作为基础绘图系统,配合专门的gghalves包,能够轻松实现半小提琴图等特殊几何图形。

首先安装并加载必要的包:

# 安装核心包(如果尚未安装) install.packages(c("ggplot2", "gghalves")) # 加载包到当前会话 library(ggplot2) library(gghalves)

为了演示云雨图的绘制过程,我们将使用经典的iris数据集。这个数据集包含了三种鸢尾花(Setosa、Versicolor和Virginica)的萼片和花瓣测量数据,非常适合展示分类变量与连续变量之间的关系。

# 查看数据结构 head(iris)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species 1 5.1 3.5 1.4 0.2 setosa 2 4.9 3.0 1.4 0.2 setosa 3 4.7 3.2 1.3 0.2 setosa 4 4.6 3.1 1.5 0.2 setosa 5 5.0 3.6 1.4 0.2 setosa 6 5.4 3.9 1.7 0.4 setosa

提示:在实际分析中,确保理解数据的结构和含义至关重要。iris数据集中的Species是分类变量,而Sepal.Width等是连续变量,这种组合正是云雨图最擅长的展示场景。

2. 基础云雨图构建三步法

2.1 第一步:创建半小提琴图层

半小提琴图是云雨图的核心组件之一,它展示了数据的概率密度分布。使用gghalves包中的geom_half_violin()函数可以轻松实现:

# 定义颜色方案 mycolor <- c("#9DCD82", "#F8B62D", "#F2997A") ggplot(iris, aes(x = Species, y = Sepal.Width, fill = Species, color = Species)) + geom_half_violin( side = "r", # 显示在右侧 adjust = 1.2, # 带宽调整系数 trim = FALSE, # 不修剪尾部 color = NA, # 无边框颜色 alpha = 0.8, # 透明度 position = position_nudge(x = 0.1) # 水平微调位置 ) + scale_fill_manual(values = rev(mycolor)) + scale_color_manual(values = rev(mycolor))

关键参数解析:

  • adjust:控制密度曲线的平滑程度,值越大曲线越平滑
  • trim:决定是否裁剪超出数据范围的尾部,FALSE保留完整形状
  • side:指定显示方向,"l"为左侧,"r"为右侧
  • position_nudge:微调图形位置,避免元素重叠

2.2 第二步:添加箱线图元素

箱线图提供了数据的五数概括(最小值、第一四分位数、中位数、第三四分位数、最大值),是理解数据分布的关键补充:

ggplot(iris, aes(x = Species, y = Sepal.Width, fill = Species, color = Species)) + geom_half_violin(side = "r", adjust = 1.2, trim = FALSE, color = NA, alpha = 0.8, position = position_nudge(x = 0.1)) + geom_boxplot( width = 0.1, # 箱体宽度 alpha = 0.7, # 透明度 outlier.shape = NA, # 隐藏离群点 position = position_nudge(x = -0.1) # 向左微调 ) + scale_fill_manual(values = rev(mycolor)) + scale_color_manual(values = rev(mycolor))

箱线图参数优化建议:

  • width:控制箱体宽度,通常设置为0.1-0.2之间
  • outlier.shape:设置为NA可避免与散点图重复显示离群点
  • position:与半小提琴图错开位置,提高可读性

2.3 第三步:整合散点图层

散点图展示了每个数据点的实际位置,为分布提供直观证据。使用position_jitter避免点重叠:

ggplot(iris, aes(x = Species, y = Sepal.Width, fill = Species, color = Species)) + geom_half_violin(side = "r", adjust = 1.2, trim = FALSE, color = NA, alpha = 0.8, position = position_nudge(x = 0.1)) + geom_boxplot(width = 0.1, alpha = 0.7, outlier.shape = NA, position = position_nudge(x = -0.1)) + geom_point( aes(x = as.numeric(Species) - 0.1), # 水平位置调整 position = position_jitter(width = 0.03), # 添加随机抖动 size = 3, # 点大小 shape = 20 # 实心圆点 ) + scale_fill_manual(values = rev(mycolor)) + scale_color_manual(values = rev(mycolor))

散点图关键设置:

  • position_jitter:width参数控制抖动范围,通常0.02-0.05效果最佳
  • as.numeric(Species):将分类变量转换为数值,便于位置微调
  • shape:20代表实心圆点,其他形状可通过不同数字指定

3. 进阶定制与优化技巧

3.1 坐标轴与主题美化

基础云雨图完成后,我们可以通过ggplot2的主题系统进一步提升视觉效果:

final_plot <- ggplot(iris, aes(x = Species, y = Sepal.Width, fill = Species, color = Species)) + geom_half_violin(side = "r", adjust = 1.2, trim = FALSE, color = NA, alpha = 0.8, position = position_nudge(x = 0.1)) + geom_boxplot(width = 0.1, alpha = 0.7, outlier.shape = NA, position = position_nudge(x = -0.1)) + geom_point(aes(x = as.numeric(Species) - 0.1), position = position_jitter(width = 0.03), size = 3, shape = 20) + scale_fill_manual(values = rev(mycolor)) + scale_color_manual(values = rev(mycolor)) + labs( title = "鸢尾花萼片宽度分布云雨图", subtitle = "展示三种鸢尾花物种的萼片宽度分布特征", x = "物种", y = "萼片宽度(cm)", caption = "数据来源: R内置iris数据集" ) + theme_minimal(base_size = 14) + theme( plot.title = element_text(face = "bold", hjust = 0.5), plot.subtitle = element_text(hjust = 0.5), legend.position = "top", panel.grid.major.x = element_blank() ) print(final_plot)

主题定制要点:

  • theme_minimal():提供简洁的基础主题,避免冗余元素
  • base_size:控制整体文字大小
  • panel.grid.major.x:移除垂直网格线,减少视觉干扰

3.2 多变量比较与分面应用

当需要比较多个变量时,可以通过分面(facet)或长格式数据转换实现:

library(tidyr) # 将数据转换为长格式 iris_long <- pivot_longer(iris, cols = -Species, names_to = "Measurement", values_to = "Value") # 绘制多变量云雨图 ggplot(iris_long, aes(x = Species, y = Value, fill = Species)) + geom_half_violin(side = "r", adjust = 1.2, trim = FALSE, alpha = 0.7) + geom_boxplot(width = 0.1, alpha = 0.7, outlier.shape = NA) + geom_point(position = position_jitter(width = 0.05), size = 2, shape = 20) + facet_wrap(~Measurement, scales = "free_y", ncol = 2) + labs(y = "测量值(cm)", x = NULL) + theme(legend.position = "bottom")

分面技巧:

  • scales = "free_y":允许每个分面有自己的y轴范围
  • ncol:控制分面排列列数
  • pivot_longer():将宽格式数据转换为长格式,适合ggplot2绘图

3.3 交互式探索与输出优化

对于需要交互探索的场景,可以结合plotly包创建动态图表:

library(plotly) # 转换为交互式图表 ggplotly(final_plot, tooltip = c("y", "fill"))

输出高质量图像用于出版时,建议使用ggsave()函数:

ggsave("raincloud_plot.png", plot = final_plot, width = 10, height = 6, dpi = 300)

输出参数建议:

  • 格式选择:PNG适合屏幕展示,PDF适合印刷出版
  • DPI设置:学术出版通常需要300-600dpi
  • 宽高比例:根据内容复杂程度调整,通常6:4或10:6效果良好

4. 实战案例与问题排查

4.1 处理非正态分布数据

当数据呈现明显偏态时,调整密度估计参数尤为重要。以下示例展示如何优化偏态数据的呈现:

# 生成右偏数据示例 set.seed(123) skewed_data <- data.frame( Group = rep(c("A", "B"), each = 100), Value = c(rgamma(100, shape = 2, scale = 2), rlnorm(100, meanlog = 1, sdlog = 0.5)) ) ggplot(skewed_data, aes(x = Group, y = Value, fill = Group)) + geom_half_violin(side = "r", adjust = 0.5, trim = FALSE, alpha = 0.7) + geom_boxplot(width = 0.15, alpha = 0.7, outlier.shape = NA) + geom_point(position = position_jitter(width = 0.05), size = 2, alpha = 0.6) + scale_y_log10() + # 对数变换y轴 labs(title = "偏态数据分布的云雨图优化", subtitle = "使用对数变换和带宽调整改善可视化效果")

偏态数据优化策略:

  1. 减小adjust参数值(如0.3-0.7),使密度曲线更贴合数据实际分布
  2. 考虑对数变换或其它数据转换方法
  3. 增加trim = FALSE确保展示完整数据范围

4.2 常见问题与解决方案

在实际应用中,可能会遇到各种技术挑战。以下是几个典型问题及其解决方法:

问题1:图形元素重叠严重

# 解决方案:精细调整各图层位置参数 ggplot(iris, aes(x = Species, y = Sepal.Width, fill = Species)) + geom_half_violin(side = "r", position = position_nudge(x = 0.15), width = 0.5) + geom_boxplot(width = 0.1, position = position_nudge(x = -0.15)) + geom_point(position = position_jitterdodge(jitter.width = 0.05, dodge.width = 0.3))

问题2:大数据集导致散点图过于密集

# 解决方案1:使用透明度调整 geom_point(position = position_jitter(width = 0.05), alpha = 0.3) # 解决方案2:使用蜂群图替代 install.packages("ggbeeswarm") geom_quasirandom(method = "smiley", width = 0.1)

问题3:多组比较时的颜色管理

# 定义可访问性友好的颜色方案 color_blind_friendly <- c("#E69F00", "#56B4E9", "#009E73", "#F0E442") ggplot(iris, aes(x = Species, y = Sepal.Width, fill = Species)) + geom_half_violin(side = "r") + scale_fill_manual(values = color_blind_friendly) + theme(legend.position = "bottom")

注意:当分类超过6-7组时,考虑使用分面或其它可视化形式,而不是依赖颜色区分。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询