pythonic生物人

同样P=0.01,为什么你的被拒稿,他的却上了顶刊?

本次使用R语言复现一下Nature medicine中的6张图,细节拉满,非常值得学习!

R绘制-b图

s41591-020-1038-6,b原图
s41591-020-1038-6,b原图
复现效果图-b图❤️
❤️复现效果图-b图❤️

✅b图是一种SCI中高频率使用的统计图:

  • 由boxplot、抖动散点图、boxplot组之间的显著性三部分组成;
  • 展示了"Low"、"Moderate"、"Severe"、"LRTI"四种不同条件下的数据与阴性对照组"Control (sero-)"以及阳性对照组"Control (sero+)"之间的差异性。

✅读入测试数据

Image

✅关键代码,

# 自定义添加p值函数
custom_compare <- function(data, ref.group = NULL) {
  comparisons <- list(
    c("Control (sero+)", "Low"),
    c("Low", "Moderate"),
    c("Moderate", "Severe"),
    c("Severe", "LRTI")
  )

  stat.test <- compare_means(
    value ~ group,
    data = data,
    method = "wilcox.test",
    ref.group = ref.group
  )

  stat.test <- stat.test %>%
    filter(
      (group1 == "Control (sero+)" & group2 == "Low") |
        (group1 == "Low" & group2 == "Moderate") |
        (group1 == "Moderate" & group2 == "Severe") |
        (group1 == "Severe" & group2 == "LRTI")
    ) %>%
    mutate(p.format = signif(p, 2))

return(stat.test)
}

# 自定义绘图函数
plot_cd25 <- function(data, cell_type, ylab, y_label_pos) {
  plot_data <- data %>% filter(type == cell_type)
  stat.test <- custom_compare(plot_data)
  ggplot(plot_data, aes(x = group, y = value)) +
    geom_boxplot(fill = NA, color = "black", outlier.shape = NA, linewidth = 0.3) +
    geom_jitter(
      aes(fill = group, shape = factor(shape)),
      width = 0.2,
      size = 5.5,
      stroke = 0.4,
      alpha = 0.8,
      color = "black"
    ) +
    stat_pvalue_manual(
      stat.test,
      label = "{p.format}",
      tip.length = 0.001,
      y.position = y_label_pos,
      size = 4.0,
      bracket.size = 0.3
    ) +
    theme_classic(base_size = 12) +

#细节个性化
    theme(
      axis.text.x = element_text(angle = 45, hjust = 1, size = 12, margin = margin(t = 10)),
      axis.title.y = element_text(size = 12),
      legend.position = "right",
      legend.box = "vertical", 
      legend.title = element_blank(),
      legend.text = element_text(size = 10),
      legend.key.height = unit(0.8, "cm"),
      legend.spacing.y = unit(0.5, "cm"),
      legend.spacing.x = unit(0.8, "cm"), 
      legend.margin = margin(t = 0.2, r = 0.5, b = 0.2, l = 0.5, unit = "cm"),
      panel.grid = element_blank(),
      axis.line = element_line(size = 0.2, color = "#333333"),
      axis.ticks = element_line(color = "#333333", size = 0.2), 
      plot.margin = margin(1, 1, 1, 1, "cm")
    )
}
Image

✅值得学习的R可视化知识点:

  • ggpubr包的函数compare_means,主要用于执行组间均值比较的统计检验(例如,Wilcoxon、t-test、ANOVA、 Kruskal-Wallis等检验),本例使用Wilcoxon检验;
# 执行组间比较,例如,
  stat.test <- compare_means(
    value ~ group,                     # 数值变量按组别分组
    data = data,                       # 输入数据
    method = "wilcox.test"# 非参数wilcox.test方法
  )

stat.test结果样式,

Image

compare_means结果在图中以p值呈现,

Image
  • R语言中的管道操作符%>%,它的核心功能是将左侧表达式的结果作为右侧函数的第一个参数传递,从而简化嵌套函数调用,提升代码可读性和流畅性。
# %>%使用案例,例如,
stat.test <- stat.test %>%
    filter(
      (group1 == "Control (sero+)" & group2 == "Low") |
        (group1 == "Low" & group2 == "Moderate") |
        (group1 == "Moderate" & group2 == "Severe") |
        (group1 == "Severe" & group2 == "LRTI")
    ) %>%
    mutate(p.format = signif(p, 2))    # 将p值格式化为2位有效数字

通过filter()保留stat.test中特定组间比较结果 ;mutate(p.format = signif(p, 2))将原始p值简化为2位有效数字;最终结果赋值给stat.test用于后续分析。

  • theme自定义主题细节,自定义坐标轴axis、图例legend、网格线grid、刻度线ticks等,
# theme自定义主题细节,例如,
    theme(
      axis.text.x = element_text(angle = 45, hjust = 1, size = 12, margin = margin(t = 10)),  # x轴标签倾斜45度
      axis.title.y = element_text(size = 12),               # y轴标题大小
      legend.position = "right",                            # 图例位置
      legend.box = "vertical",                              # 图例垂直排列
      legend.title = element_blank(),                       # 无图例标题
      legend.text = element_text(size = 10),                # 图例文本大小
      legend.key.height = unit(0.8, "cm"),                  # 图例键高度
      legend.spacing.y = unit(0.5, "cm"),                   # 图例垂直间距
      legend.spacing.x = unit(0.8, "cm"),                   # 图例水平间距
      legend.margin = margin(t = 0.2, r = 0.5, b = 0.2, l = 0.5, unit = "cm"),  # 图例外边距
      panel.grid = element_blank(),                         # 无网格线
      axis.line = element_line(size = 0.2, color = "#333333"),  # 坐标轴线样式
      axis.ticks = element_line(color = "#333333", size = 0.2),  # 刻度线样式
      plot.margin = margin(1, 1, 1, 1, "cm")               # 图形外边距
    )
Image

R绘制-abcd图

s41591-020-1038-6,abcd原图,
s41591-020-1038-6,abcd原图,
复现效果图-abcd图❤️
❤️复现效果图-abcd图❤️

✅abcd图含义:

  • 通过箱线图+散点图展示四类细胞因子(IL-8、IL-6、IL-10、IP-10)在血浆中的浓度分布;
  • 展示了"Low"、"Moderate"、"Severe"、"LRTI"四种不同条件下的数据与阴性对照组"Control (sero-)"以及阳性对照组"Control (sero+)"之间的差异性。

✅读入数据,

Image

✅关键代码,

# 计算y轴范围的函数(对数刻度适配)
calculate_limits <- function(data) {
  data_range <- range(data$concentration, na.rm = TRUE)
  lower_limit <- max(0.1, data_range[1] * 0.5)
  upper_limit <- min(data_range[2] * 3, 1e5)
  c(lower_limit, upper_limit)
}

create_plot <- function(data, title, y_label, y_limits, y_breaks) {
  p <- ggplot(data, aes(x = class_dss, y = concentration)) +
    geom_boxplot(
      color = "black", fill = NA, outlier.shape = NA,
      width = 0.8, size = 0.3
    ) +
    geom_jitter(
      aes(fill = class_dss, shape = factor(shape)),
      color = "black", size = 3.5, width = 0.2,
      stroke = 0.4, alpha = 0.8
    ) +
    scale_y_log10(
      breaks = y_breaks,
      labels = trans_format("log10", math_format(10^.x)),
      expand = expansion(mult = c(0.05, 0.2))
    ) +

# 精确控制每个p值标签的y位置
    stat_compare_means(
      comparisons = comparisons,
      method = "wilcox.test",
      label = "p.format", # 显示格式化的p值
      label.y = c(
        log10(y_limits[2]) * 0.9, # 第一组比较位置
        log10(y_limits[2]) * 1.0, # 第二组比较位置(上移)
        log10(y_limits[2]) * 0.9, # 第三组比较位置(恢复)
        log10(y_limits[2]) * 1.1# 第四组比较位置(上移)
      ),
      size = 3.5,
      color = "black",
      step.increase = 0.025, # 控制p值标签的垂直间距
      tip.length = 0.001# 缩短连接线长度
    ) +
# 添加对数刻度的小刻度线
    annotation_logticks(
      sides = "l",
      short = unit(0.05, "cm"),
      mid = unit(0.1, "cm"),
      long = unit(0.15, "cm"),
      color = "#333333", linewidth = 0.3
    )

return(p)
}
Image

这张图和上一部分的图重叠的东西不再赘述。

✅值得学习的R可视化知识点:

  • calculate_limits函数灵活控制y轴的刻度范围,让图的布局更符合审美,
Image
# 计算y轴范围的函数(对数刻度适配)
calculate_limits <- function(data) {
  data_range <- range(data$concentration, na.rm = TRUE)
  lower_limit <- max(0.1, data_range[1] * 0.5)
  upper_limit <- min(data_range[2] * 3, 1e5)
  c(lower_limit, upper_limit)
}
Image

效果一目了然!

  • 灵活手动控制p值标签的y位置
Image
label.y = c(# 精确控制每个p值标签的y位置
        log10(y_limits[2]) * 0.9, # 第一组比较位置(y上限的90%)
        log10(y_limits[2]) * 1.0, # 第二组比较位置(100%,上移避免重叠)
        log10(y_limits[2]) * 0.9, # 第三组比较位置(恢复90%)
        log10(y_limits[2]) * 1.1# 第四组比较位置(110%,进一步上移)
      ),
Image
  • annotation_logticks添加对数刻度的小刻度线,用于在对数坐标轴上添加精细的刻度线(minor ticks),帮助更清晰地展示对数尺度下的数据分布,
# 添加对数刻度的小刻度线
    annotation_logticks(
      sides = "l",               # 仅左侧显示
      short = unit(0.05, "cm"),  # 短刻度长度
      mid = unit(0.1, "cm"),     # 中等刻度长度
      long = unit(0.15, "cm"),   # 长刻度长度
      color = "#333333",         # 刻度线颜色
      linewidth = 0.3# 线宽
    ) 
Image

abcd看似简单的图,其实,包含大量R可视化细节。

本期结束!


测试数据+详细代码,后期会加入👉《保姆级R可视化教程》

加入学习(备注:299)

图片