绘制超好看的云雨图和小提琴图!

云雨图&小提琴图的作用

1. 云雨图(Half-Violin Plot)
定义

云雨图是一种结合了 小提琴图散点图 的图形表现形式,其中:

  • 一侧展示小提琴图(通常用于显示数据的分布密度)。
  • 另一侧叠加散点图,展示每个数据点的原始数值分布。
特点
  • 半小提琴图(half-violin):将传统小提琴图切为一半,通常位于图形的右侧或左侧。
  • 散点图叠加:用于展示每个数据点的具体位置,从而避免分布密度掩盖数据细节。
作用
  • 数据分布和细节并重
    • 小提琴部分展示数据的全局分布(如峰值和尾部情况)。
    • 散点部分提供具体的观测点分布,帮助发现异常值或分布的离散程度。
  • 易于分组对比:适合分组数据的可视化(如不同实验条件、类别变量)。

2. 小提琴图(Violin Plot)
定义

小提琴图是一种结合了 箱线图核密度图 的数据可视化工具,用于描述数据的分布形态。

特点
  • 中心部分包含一个 箱线图,显示分布的五数概要(最小值、第一四分位数、中位数、第三四分位数、最大值)。
  • 两侧对称展示 核密度估计,表示数据的分布密度。
  • 形状宽度反映数据分布的密集程度(宽的部分表示该范围内的数据点更多)。
作用
  • 显示数据分布形态
    • 比单纯的箱线图更详细,能够直观地看到数据分布的偏态、峰值和多模态特征。
  • 数据对比
    • 特别适合多个分组的数据比较。
    • 不同宽度的区域展示了各分组的分布差异,例如分布是否对称、是否存在多个峰值。
  • 整合数据摘要
    • 通过同时显示箱线图和核密度估计,小提琴图提供了数据的全景视角。



数据结构



云雨图代码

1. 导入库和读取数据

library(ggplot2)
library(dplyr)
library(RColorBrewer)
library(viridis)
library(ggpubr)
library(rstatix)
library(gghalves)
library(patchwork)
library(openxlsx)

data1 <- read.xlsx("aaa.xlsx")
data1$prob <- factor(data1$prob)
data1$outcome <- factor(data1$outcome)
data1$delay <- as.numeric(data1$delay)
  • 加载库

    • ggplot2:主要用于数据可视化。
    • dplyr:用于数据过滤和处理。
    • openxlsx:读取 Excel 数据。
    • 其他库(如 gghalves)提供了额外的绘图功能,如半小提琴图。
  • 数据预处理

    • 使用 read.xlsx 读取 Excel 文件 aaa.xlsx
    • proboutcome 转换为因子(分类变量),便于分组绘图。
    • delay 转换为数值型,以便用于数值分布图。

2. 定义颜色映射

colors = c('#889ECE','#F4E636','#29C4A1','#F3640E','lightgreen')
names(colors) = c('20','30','70','80','90')
  • 定义了一组颜色 colors,并将颜色与 prob 的具体分类值(20、30、70、80、90)绑定。
  • scale_fill_manualscale_color_manual 后续会引用这些颜色,用于为小提琴图、箱线图和散点图分组上色。

3. 按分组绘图

for (outcome_id in unique(data1$outcome)) {
  data_outcome <- data1 %>%
    filter(outcome == outcome_id)
  • 循环
    • 遍历 outcome 的所有唯一值。
    • 使用 filter 筛选出当前循环下的子数据 data_outcome,确保每个分组独立绘图。

4. 构建图形

p <- ggplot(data_outcome, aes(x = prob, y = delay)) +
  geom_half_violin(aes(fill = prob, color = prob), side = 'r', position = position_nudge(x = 0.35, y = 0)) +
  geom_boxplot(aes(fill = prob, color = prob), outliers = FALSE, width = 0.12, cex = 0.8, alpha = 0.5, position = position_nudge(x = 0.22, y = 0)) +
  geom_jitter(color = "grey60", width = 0.1, size = 0.6, alpha = 0.9) +
  ...

绘图层解析

  1. geom_half_violin

    • 功能:绘制半小提琴图,展示每组数据的分布形态。
    • 参数
      • fillcolorprob 分类着色。
      • side = 'r':小提琴图在右侧。
      • position_nudge:将小提琴图稍微向右平移,避免与其他图层重叠。
  2. geom_boxplot

    • 功能:绘制箱线图,显示分组的五数概要(最小值、四分位数和最大值)。
    • 参数
      • outliers = FALSE:隐藏离群点。
      • width = 0.12:调整箱线图宽度。
      • position_nudge:将箱线图向右平移,与小提琴图对齐。
  3. geom_jitter

    • 功能:叠加散点图,展示每个数据点的分布。
    • 参数
      • color = "grey60":散点颜色设置为灰色。
      • width = 0.1:在 X 轴方向上添加少量随机抖动,避免散点重叠。

5. 坐标轴与配色

scale_color_manual(values = colors) + 
scale_fill_manual(values = colors) +
scale_y_continuous(limits = c(0,50)) +
scale_x_discrete() +
coord_flip()
  • 颜色

    • scale_color_manualscale_fill_manual 使用自定义颜色 colors
  • 坐标轴

    • scale_y_continuous 设置 Y 轴范围为 [0, 50]。
    • coord_flip 将 X 和 Y 轴翻转,使分类变量 prob 位于垂直方向。

6. 图表标签与标题

labs(
  x = "Probability (%)", 
  y = "Delay (Months)", 
  fill = "概率水平", 
  color = "概率水平"
) + 
ggtitle(paste("个体等量参数转换点---", outcome_id, "元"))
  • 标签

    • 自定义 X 轴和 Y 轴的标题。
    • 为图例设置标题 fillcolor,同时支持中文显示。
  • 标题

    • ggtitle 动态生成标题,包含当前分组的 outcome 值。

7. 自定义主题

theme_minimal() + 
theme(
  text = element_text(size = 13),
  plot.title = element_text(size = 15.5, face = "bold", family = "Arial", color = "black", hjust = 0.5),
  axis.text.x = element_text(size = 14, family = "Arial", color = "black", margin = margin(t = 6)),
  axis.text.y = element_text(size = 14, family = "Arial", color = "black", margin = margin(r = 4)),
  ...
)
  • 使用 theme_minimal 创建简洁的主题,并细化各部分样式。
  • 细节调整
    • 标题字体设置为加粗 (face = "bold")。
    • 轴标签、图例标题和文本字体大小分别调整。

8. 保存图像

ggsave(filename = paste0("云雨图_修订", outcome_id, ".png"), plot = p, width = 8, height = 6)
  • 每次循环保存当前分组的图像,文件名包含分组信息 outcome_id
  • 图像格式为 PNG,尺寸为 8 × 6 英寸。

总结

# 加载必要的库
library(ggplot2)        # 数据可视化
library(dplyr)          # 数据处理
library(RColorBrewer)   # 调色板
library(viridis)        # 色盲友好配色方案
library(ggpubr)         # 增强 ggplot2 功能
library(rstatix)        # 统计分析辅助
library(gghalves)       # 半小提琴图
library(patchwork)      # 组合图表
library(openxlsx)       # 读取 Excel 数据

# 读取数据
data1 <- read.xlsx("aaa.xlsx")       # 读取 Excel 文件
data1$prob <- factor(data1$prob)    # 将 prob 转换为因子变量
data1$outcome <- factor(data1$outcome) # 将 outcome 转换为因子变量
data1$delay <- as.numeric(data1$delay) # 将 delay 转换为数值型变量

# 自定义颜色映射
colors <- c('#889ECE', '#F4E636', '#29C4A1', '#F3640E', 'lightgreen')
names(colors) <- c('20', '30', '70', '80', '90')  # 将颜色与 prob 分类值绑定

# 循环绘图并保存
for (outcome_id in unique(data1$outcome)) {
  # 筛选当前分组数据
  data_outcome <- data1 %>%
    filter(outcome == outcome_id)
  
  # 创建图形
  p <- ggplot(data_outcome, aes(x = prob, y = delay)) +
    # 添加半小提琴图
    geom_half_violin(
      aes(fill = prob, color = prob),
      side = 'r',                           # 半小提琴在右侧
      position = position_nudge(x = 0.35, y = 0) # 平移位置避免重叠
    ) +
    # 添加箱线图
    geom_boxplot(
      aes(fill = prob, color = prob),
      outliers = FALSE,                    # 不显示离群点
      width = 0.12,                        # 箱线图宽度
      cex = 0.8,                           # 边框线宽
      alpha = 0.5,                         # 半透明效果
      position = position_nudge(x = 0.22, y = 0) # 平移位置
    ) +
    # 添加散点图
    geom_jitter(
      color = "grey60",                    # 散点颜色
      width = 0.1,                         # 水平方向抖动
      size = 0.6,                          # 散点大小
      alpha = 0.9                          # 不透明度
    ) +
    # 自定义颜色映射
    scale_color_manual(values = colors) + 
    scale_fill_manual(values = colors) +
    # 设置坐标轴范围
    scale_y_continuous(limits = c(0, 50)) + 
    scale_x_discrete() +
    coord_flip() +                         # 翻转坐标轴(X 和 Y 交换位置)
    # 设置标签
    labs(
      x = "Probability (%)",               # X 轴标签
      y = "Delay (Months)",                # Y 轴标签
      fill = "概率水平",                     # 填充图例标题
      color = "概率水平"                    # 边框图例标题
    ) +
    # 设置图表标题
    ggtitle(paste("个体等量参数转换点---", outcome_id, "元")) + 
    # 设置主题样式
    theme_minimal() +
    theme(
      text = element_text(size = 13),                       # 全局文字大小
      plot.title = element_text(size = 15.5, face = "bold", family = "Arial", color = "black", hjust = 0.5),
      axis.text.x = element_text(size = 14, family = "Arial", color = "black", margin = margin(t = 6)),
      axis.text.y = element_text(size = 14, family = "Arial", color = "black", margin = margin(r = 4)),
      axis.title.x = element_text(size = 15, family = "Arial", color = "black"),
      axis.title.y = element_text(size = 15, family = "Arial", color = "black"),
      legend.title = element_text(size = 11, family = "Arial", color = "black", face = "bold"),
      legend.text = element_text(size = 10, family = "Arial", color = "black"),
      axis.ticks.x = element_line(linewidth = 0.6),         # X 轴刻度线宽度
      axis.ticks.y = element_line(linewidth = 0.6),         # Y 轴刻度线宽度
      axis.ticks.length = unit(-0.15, "cm"),                # 刻度线长度
      axis.line = element_line(linewidth = 0.7),            # 坐标轴线宽度
      panel.grid = element_blank()                          # 去除网格线
    )
  
  # 保存图像
  ggsave(
    filename = paste0("云雨图_修订", outcome_id, ".png"), # 动态生成文件名
    plot = p, 
    width = 8, 
    height = 6
  )
}


小提琴图代码

在上面代码的基础上稍微更改一下即可

# 加载必要的库
library(ggplot2)        # 数据可视化
library(dplyr)          # 数据操作
library(openxlsx)       # 读取 Excel 数据

# 读取数据
data1 <- read.xlsx("aaa.xlsx")       # 读取 Excel 文件
data1$prob <- factor(data1$prob)    # 将 prob 转换为因子变量
data1$outcome <- factor(data1$outcome) # 将 outcome 转换为因子变量
data1$delay <- as.numeric(data1$delay) # 将 delay 转换为数值型变量

# 按分组绘制并保存图形
for (outcome_id in unique(data1$outcome)) {
  # 筛选当前分组的数据
  data_outcome <- data1 %>%
    filter(outcome == outcome_id)
  
  # 绘制图形
  p <- ggplot(data_outcome, aes(x = prob, y = delay, fill = prob)) +
    # 小提琴图
    geom_violin(trim = FALSE, scale = "width", color = NA, alpha = 0.35) +
    # trim = FALSE 保留尾部;scale = "width" 保持宽度一致;color = NA 去除边框
    
    # 叠加箱线图
    geom_boxplot(width = 0.2, color = "black", outlier.shape = NA, alpha = 0.4) +
    # width 调整宽度;color 设置边框颜色;outlier.shape = NA 隐藏离群点;alpha 设置透明度
    
    # 叠加散点图
    geom_jitter(aes(color = prob), width = 0.2, height = 0, alpha = 1) +
    # width = 0.2 添加抖动;height = 0 保持垂直对齐;alpha = 1 不透明
    
    # 自定义坐标轴
    scale_x_discrete() +
    scale_y_continuous(breaks = seq(0, 60, by = 20)) +
    coord_cartesian(ylim = c(0, 60)) +
    # coord_cartesian 限制 Y 轴范围为 0 到 60
    
    # 自定义填充和边框颜色
    scale_fill_manual(values = c("palevioletred", "peachpuff", "lightgreen", "lightblue", "plum")) +
    scale_color_manual(values = c("palevioletred", "peachpuff", "lightgreen", "lightblue", "plum")) +
    
    # 添加标签
    labs(
      x = "Probability (%)",              # X 轴标签
      y = "Delay (Months)",               # Y 轴标签
      fill = "概率水平",                   # 填充图例标题
      color = "概率水平"                   # 边框图例标题
    ) +
    
    # 添加图表标题
    ggtitle(paste("个体等量参数转换点---", outcome_id, "元")) +
    
    # 设置主题
    theme_minimal() +
    theme(
      text = element_text(size = 13),                       # 全局文本大小
      plot.title = element_text(size = 15.5, face = "bold", family = "Arial", color = "black", hjust = 0.5),
      axis.text.x = element_text(size = 14, family = "Arial", color = "black", margin = margin(t = 6)),
      axis.text.y = element_text(size = 14, family = "Arial", color = "black", margin = margin(r = 4)),
      axis.title.x = element_text(size = 15, family = "Arial", color = "black"),
      axis.title.y = element_text(size = 15, family = "Arial", color = "black"),
      legend.title = element_text(size = 11, family = "Arial", color = "black", face = "bold"),
      legend.text = element_text(size = 10, family = "Arial", color = "black"),
      axis.ticks.x = element_line(linewidth = 0.6),
      axis.ticks.y = element_line(linewidth = 0.6),
      axis.ticks.length = unit(-0.15, "cm"),
      axis.line = element_line(linewidth = 0.7),
      panel.grid = element_blank()
    )
  
  # 保存图像
  ggsave(
    filename = paste0("小提琴图_", outcome_id, "元", ".png"), # 文件名动态生成
    plot = p,
    width = 8, 
    height = 6
  )
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱做科研的桶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值