pythonic生物人

复现IF 15期刊图,换数据即可用!

看到一篇Nature communications中的两张图很nice,

ref: s41467-025-61202-5
ref: s41467-025-61202-5

下面使用R语言复现一下a图和b图,

复现效果图-a图
复现效果图-a图
复现效果图-b图
复现效果图-b图

R绘制-a图

a图由3个密度图组成,图中图的排列方式值得借鉴:

  • 主密度图(6,327个数据)
  • 上子密度图(5,181个数据)
  • 下子密度图(1,146个数据)

读入测试数据,

Image

关键代码,

# 主密度图
main_plot <- ggplot(density_nc_data, aes(x = copy_number)) +
  geom_density(fill = purple_color, color = purple_color2, linewidth = 0.6) +
  annotate(
"segment",
    x = 8, xend = 8, y = 0, yend = 0.68, # 指定y轴范围
    linetype = "dashed",
    linewidth = 0.4,
    color = purple_color2
  ) +
  scale_x_log10(
    limits = c(1, 1000),
    breaks = c(1, 10, 100, 1000)
  ) +
  scale_y_continuous(breaks = seq(0, 0.7, by = 0.1)) + # 设置y轴刻度
  labs(x = "Plasmid copy number", y = "Density") +
  nature_theme

# 上子密度图
gram_neg_plot <- ggplot(subset(density_nc_data, type == "Gram-negative"), aes(x = copy_number)) +
  geom_density(fill = purple_color1, color = gray_color) +
  scale_x_log10(
    limits = c(1, 1000),
    breaks = c(1, 10, 100, 1000)
  ) +
  scale_y_continuous(breaks = seq(0, 0.7, by = 0.1)) +
  labs(title = "Gram-negative bateria", x = "", y = "") +
  nature_theme +
  theme(plot.margin = margin(2, 2, 8, 8))

# 下子密度图
gram_pos_plot <- ggplot(subset(density_nc_data, type == "Gram-positive"), aes(x = copy_number)) +
  geom_density(fill = purple_color1, color = gray_color) +
  scale_x_log10(
    limits = c(1, 1000),
    breaks = c(1, 10, 100, 1000)
  ) +
  scale_y_continuous(breaks = seq(0, 0.7, by = 0.1)) +
  labs(title = "Gram-positive bateria", x = "", y = "") +
  nature_theme +
  theme(plot.margin = margin(2, 2, 8, 8))

# 组合3个密度图并添加样本量标签
final_plot <- ggdraw() +
  draw_plot(main_plot) +
  draw_plot(gram_neg_plot, x = 0.6, y = 0.6, width = 0.35, height = 0.3) +
  draw_plot(gram_pos_plot, x = 0.6, y = 0.25, width = 0.35, height = 0.3) +

# 添加标签 
  draw_label(
    label = paste0("n = ", format(n_total, big.mark = ",")),
    x = 0.65, y = 0.6, hjust = 1, size = 9, color = purple_color2
  ) +
  draw_label(
    label = paste0("n = ", format(n_gram_neg, big.mark = ",")),
    x = 0.9, y = 0.8, hjust = 1, size = 9, color = gray_color
  ) +
  draw_label(
    label = paste0("n = ", format(n_gram_pos, big.mark = ",")),
    x = 0.9, y = 0.4, hjust = 1, size = 9, color = gray_color
  ) +
  draw_label(
    label = "All plasmids in the dataset",
    x = 0.5, y = 0.97, hjust = 0.5, size = 12
  )

final_plot
Image

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

  • cowplot中的ggdraw、draw_plot强大子图拼接功能;
# 例如
ggdraw() +
  draw_plot(main_plot) +
  draw_plot(gram_neg_plot, x = 0.6, y = 0.6, width = 0.35, height = 0.3) +
  draw_plot(gram_pos_plot, x = 0.6, y = 0.25, width = 0.35, height = 0.3)
  • cowplot中的draw_label 添加文本标签功能
# 例如
draw_label(
    label = paste0("n = ", format(n_total, big.mark = ",")),
    x = 0.65, y = 0.6, hjust = 1, size = 9, color = purple_color2
  ) 

R绘制-b图

b图是分面山峦图,山峦图的作用、使用场景,之前有写过教程:

读入测试数据,

Image

关键代码,

# 主图
main_plot <- ggplot(density_ridges_nc_data, aes(x = value, y = genus, fill = genus, color = genus)) +
  geom_density_ridges(
    scale = 1.5,
    rel_min_height = 0,
    alpha = 0.6,
    size = 0.3
  ) +
  facet_wrap(~group, scales = "free_y", ncol = 2) +
# 设置图中文本
  ggtext::geom_richtext(
    data = abundance,
    aes(x = label_x, y = genus, label = label_text, color = genus),
    inherit.aes = FALSE,
    hjust = 0.2,
    vjust = 0.6,
    size = 4.0,
    fill = NA, label.color = NA,
    show.legend = FALSE
  ) +
  scale_fill_manual(values = color_map) +
  scale_color_manual(values = color_map) +
  scale_x_log10(
    breaks = c(1, 10, 100, 1000, 10000),
    labels = c("1", "10", "100", "1,000", "10,000"),
    expand = expansion(mult = c(0.01, 0.5))
  ) +
  scale_y_discrete(expand = expansion(mult = c(0.1, 0.3))) +
  nature_theme

# 添加共用 x 轴标题
final_plot <- main_plot / plot_spacer() +
  plot_layout(heights = c(1, 0.05)) &
  theme(plot.margin = margin(5, 5, 5, 5)) &
  labs(x = "Plasmid copy number")

# 展示图形
final_plot
Image

这个图,看似很简单,但是,有些细节值得学习!

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

  • ggtext渲染混用文本标签(斜体拉丁文细菌属名 + 正常数字)
# 例如,
ggtext::geom_richtext(
    data = abundance,
    aes(x = label_x, y = genus, label = label_text, color = genus),
    inherit.aes = FALSE,
    hjust = 0.2,
    vjust = 0.6,
    size = 4.0,
    fill = NA, label.color = NA,
    show.legend = FALSE
  ) 
Image
  • 控制xy轴两端的留白比例
# 控制y轴
scale_y_discrete(expand = expansion(mult = c(0.1, 0.3))) # 控制y轴上下端空白比例

# 控制x轴
scale_x_log10(
    breaks = c(1, 10, 100, 1000, 10000),
    labels = c("1", "10", "100", "1,000", "10,000"),
    expand = expansion(mult = c(0.01, 0.5)) # 控制x轴左右端空白比例
  ) 
Image

设置scale_y_discrete(expand = expansion(mult = c(0.1, 0.3))) ,

Image

本期结束!


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

加入学习(备注:299)

图片