基于 R 语言的科研论文绘图技巧详解(1)

简介: 在查阅文献的过程中,看到了几幅非常不错的出版图,今天就跟着小编一起学习下,他们是怎么使用 R 绘制出来的。

简介


在查阅文献的过程中,看到了几幅非常不错的出版图,今天就跟着小编一起学习下,他们是怎么使用 R 绘制出来的。

W9_P5EIVXTFD2Q$D3H@$C{L.png

今天主要介绍第一幅图(A),初步观察来看,改图是由两张照片合并而成,并且在上面加上了箭头、圆圈,来说明作者想表达的问题。

后面几幅图会一一介绍,读者在学习过程中,可以将内部学到的知识点应用到自己的图形绘制中。

那我们来看看,他是怎么实现这个功能的吧,对应代码可在 GitHub - marco-meer/scifig_plot_examples_R: Scientific publication figure plotting examples with R[1] 可以找到。


主要知识点

  • 学会如何导入图形,并将其并排展示;
  • 学会设置自定义主题,简化代码,统一主题,方便绘制其他图形使用;
  • 学会使用 ggplot2 包内置参数添加文字已经其他其他修饰图标。


绘图


加载包

首先加载一些需要使用到的包。

library(ggplot2) # Grammar of graphics
library(cowplot) # Arranging multiple plots into a grid
library(png)     # Load JPEG, PNG and TIFF format 
library(scales)  # Generic plot scaling methods
library(viridis) # Default color maps from 'matplotlib'
library(grid)    # A rewrite of the graphics layout capabilities
library(magick)  # graphics and image processing
library(rsvg)    # Render svg image into a high quality bitmap
library(ggforce) # Collection of additional ggplot stats + geoms


设置主题

接下来,为了方便起见,作者在绘图前设置好了主题,并将该函数命名为 my_theme

这个主题并没有在第一幅图中使用,但是在后面几幅图中都会使用,这里先将其展示下。使用方式会在下一篇推文中进行介绍。

手动修改大部分面板,具体可以参考本篇文章[2]。或者观看我在 B 站发布的《R 语言可视化教程》,里面也有一些简单主题设置介绍。

# 全局字体大小
base_size = 12 
# 手动修改大部分面板
# documentation: https://ggplot2.tidyverse.org/reference/theme.html
my_theme <-  function() {
  theme(
    aspect.ratio = 1,
    axis.line =element_line(colour = "black"),  
    # shift axis text closer to axis bc ticks are facing inwards
    axis.text.x = element_text(size = base_size*0.8, color = "black", 
                               lineheight = 0.9,
                               margin=unit(c(0.3,0.3,0.3,0.3), "cm")), 
    axis.text.y = element_text(size = base_size*0.8, color = "black", 
                               lineheight = 0.9,
                               margin=unit(c(0.3,0.3,0.3,0.3), "cm")),  
    axis.ticks = element_line(color = "black", size  =  0.2),  
    axis.title.x = element_text(size = base_size, 
                                color = "black", 
                                margin = margin(t = -5)), 
    # t (top), r (right), b (bottom), l (left)
    axis.title.y = element_text(size = base_size, 
                                color = "black", angle = 90,
                                margin = margin(r = -5)),  
    axis.ticks.length = unit(-0.3, "lines"),  
    legend.background = element_rect(color = NA, 
                                     fill = NA), 
    legend.key = element_rect(color = "black",  
                              fill = "white"),  
    legend.key.size = unit(0.5, "lines"),  
    legend.key.height = NULL,  
    legend.key.width = NULL,      
    legend.text = element_text(size = 0.6*base_size, 
                               color = "black"),  
    legend.title = element_text(size = 0.6*base_size, 
                                face = "bold", 
                                hjust = 0, 
                                color = "black"),  
    legend.text.align = NULL,  
    legend.title.align = NULL,  
    legend.direction = "vertical",  
    legend.box = NULL, 
    panel.background = element_rect(fill = "white", 
                                    color  =  NA),  
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    plot.title = element_text(size = base_size, 
                              color = "black"), 
  ) 
}


绘图步骤详解


由于代码复杂,知识点较多,为了读者更好理解代码逻辑和含义,小编将其分布讲解。最后再将完整代码放到本节末。


导入图片

首先使用 magick 包中的 image_read() 导入两幅图,并通过image_flip()进行转化。

img1 <- magick::image_flip(magick::image_read("./image1.jpg"))
img2 <-  magick::image_flip(magick::image_read("./image2.png"))

接下来,将两幅图并行合并,放置到一幅图中。这里的代码,小编也是第一次见。通过 grid 包中的 grid.raster() 设置光栅(raster)对象,并使用 annotation_custom()设置摆放位置。这时候得到的结果是

ggplot() +
  annotation_custom(rasterGrob(image =  img1, 
                               x=0.27,
                               y=0.49,
                               width = unit(0.45,"npc"),
                               height = unit(0.87,"npc")), 
                    -Inf, Inf, -Inf, Inf) +
  annotation_custom(rasterGrob(image = img2, 
                               x=0.73,
                               y=0.49,
                               width = unit(0.45,"npc"),
                               height = unit(0.87,"npc")), 
                    -Inf, Inf, -Inf, Inf)

DSM6KG@LSD2_JGNHM`TQSUX.png


其他修饰图标

加入修饰图标,来说明问题。主要使用 geom_ellipse() 构建椭圆形,geom_segment() 增加线段(箭头设置,在内部参数 arrow 中)。

geom_ellipse(aes(x0 = 0.25, 
                 y0 = 0.3,
                 a = 0.1, 
                 b = 0.04, 
                 angle = 0),
              color="yellow",
              size=1) +
  scale_x_continuous(limits = c(0,1))+ # 设置 x 轴坐标范围
  scale_y_continuous(limits=c(0,1)) +
  geom_segment(aes(x=0.15,
                   xend=0.2,
                   y=0.75,
                   yend=0.7),
               arrow = arrow(length=unit(0.30,"cm"),
                             ends="last", 
                             type = "closed"),
               size = 1,
               color="white") +
  geom_segment(aes(x=0.3,
                   xend=0.9,
                   y=0.7,
                   yend=0.7),
               arrow = arrow(length=unit(0.30,"cm"),
                             ends="both", 
                             type = "closed"),
               size = 1,
               color="red")


添加文字

使用 annotate() 添加文字("text"),使用 geom_segment() 添加线段(右下角白色的线段),这里没有设置箭头。

annotate("text", x = 0.25, y = 0.5, label = "PNG",color="white") +
  annotate("text", x = 0.75, y = 0.5, label = "JPEG",color="white") +
  annotate("text", x = 0.25, y = 1, label = "image 1",color="black") +
  annotate("text", x = 0.75, y = 1, label = "image 2",color="black") +
  annotate("text", x = 0.39, y = 0.07, label = "20~mu*m",color="white",parse=T) +
  annotate("text", x = 0.89, y = 0.07, label = "20~mu*m",color="white",parse=T) +
  geom_segment(aes(x=0.33,xend=0.45,y=0.03,yend=0.03), size = 2,color="white") +
  geom_segment(aes(x=0.83,xend=0.95,y=0.03,yend=0.03),size = 2,color="white")

这时候得到的结果为:

X(V)H3YC_26EM~EGP(J18SY.png


微调主题

去除主题,并修改图形边界。

theme_void() +# blank plot w/o axes etc.
  theme(plot.margin = unit(c(-0,0,1,0), "cm"),
        aspect.ratio = 1)

K@1IHG~XL1OGTQ0_CV{RV6W.png


完整代码


library(ggplot2) # Grammar of graphics
library(cowplot) # Arranging multiple plots into a grid
library(png)     # Load JPEG, PNG and TIFF format 
library(scales)  # Generic plot scaling methods
library(viridis) # Default color maps from 'matplotlib'
library(grid)    # A rewrite of the graphics layout capabilities
library(magick)  # graphics and image processing
library(rsvg)    # Render svg image into a high quality bitmap
library(ggforce) # Collection of additional ggplot stats + geoms
# global font size
base_size = 12 
# Manual theme for most panels
# documentation: https://ggplot2.tidyverse.org/reference/theme.html
my_theme <-  function() {
  theme(
    aspect.ratio = 1,
    axis.line =element_line(colour = "black"),  
    # shift axis text closer to axis bc ticks are facing inwards
    axis.text.x = element_text(size = base_size*0.8, color = "black", 
                               lineheight = 0.9,
                               margin=unit(c(0.3,0.3,0.3,0.3), "cm")), 
    axis.text.y = element_text(size = base_size*0.8, color = "black", 
                               lineheight = 0.9,
                               margin=unit(c(0.3,0.3,0.3,0.3), "cm")),  
    axis.ticks = element_line(color = "black", size  =  0.2),  
    axis.title.x = element_text(size = base_size, 
                                color = "black", 
                                margin = margin(t = -5)), 
    # t (top), r (right), b (bottom), l (left)
    axis.title.y = element_text(size = base_size, 
                                color = "black", angle = 90,
                                margin = margin(r = -5)),  
    axis.ticks.length = unit(-0.3, "lines"),  
    legend.background = element_rect(color = NA, 
                                     fill = NA), 
    legend.key = element_rect(color = "black",  
                              fill = "white"),  
    legend.key.size = unit(0.5, "lines"),  
    legend.key.height =NULL,  
    legend.key.width = NULL,      
    legend.text = element_text(size = 0.6*base_size, 
                               color = "black"),  
    legend.title = element_text(size = 0.6*base_size, 
                                face = "bold", 
                                hjust = 0, 
                                color = "black"),  
    legend.text.align = NULL,  
    legend.title.align = NULL,  
    legend.direction = "vertical",  
    legend.box = NULL, 
    panel.background = element_rect(fill = "white", 
                                    color  =  NA),  
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    plot.title = element_text(size = base_size, 
                              color = "black"), 
  ) 
}
# Panel A ----
img1 <- magick::image_flip(magick::image_read("./image1.jpg"))
img2 <-  magick::image_flip(magick::image_read("./image2.png"))
panel_A <- ggplot() +
  annotation_custom(rasterGrob(image =  img1, 
                               x=0.27,
                               y=0.49,
                               width = unit(0.45,"npc"),
                               height = unit(0.87,"npc")), 
                    -Inf, Inf, -Inf, Inf) +
  annotation_custom(rasterGrob(image = img2, 
                               x=0.73,
                               y=0.49,
                               width = unit(0.45,"npc"),
                               height = unit(0.87,"npc")), 
                    -Inf, Inf, -Inf, Inf) +
  geom_ellipse(aes(x0 = 0.25, 
                            y0 = 0.3,
                            a = 0.1, 
                            b = 0.04, 
                            angle = 0),
                        color="yellow",
                        size=1)+
  scale_x_continuous(limits = c(0,1))+
  scale_y_continuous(limits=c(0,1)) +
  geom_segment(aes(x=0.15,
                   xend=0.2,
                   y=0.75,
                   yend=0.7),
               arrow = arrow(length=unit(0.30,"cm"),
                             ends="last", 
                             type = "closed"),
               size = 1,
               color="white") +
  geom_segment(aes(x=0.3,
                   xend=0.9,
                   y=0.7,
                   yend=0.7),
               arrow = arrow(length=unit(0.30,"cm"),
                             ends="both", 
                             type = "closed"),
               size = 1,
               color="red") +
  annotate("text", x = 0.25, y = 0.5, label = "PNG",color="white") +
  annotate("text", x = 0.75, y = 0.5, label = "JPEG",color="white") +
  annotate("text", x = 0.25, y = 1, label = "image 1",color="black") +
  annotate("text", x = 0.75, y = 1, label = "image 2",color="black") +
  annotate("text", x = 0.39, y = 0.07, label = "20~mu*m",color="white",parse=T) +
  annotate("text", x = 0.89, y = 0.07, label = "20~mu*m",color="white",parse=T) +
  geom_segment(aes(x=0.33,xend=0.45,y=0.03,yend=0.03), size = 2,color="white") +
  geom_segment(aes(x=0.83,xend=0.95,y=0.03,yend=0.03),size = 2,color="white")  + 
  theme_void() +# blank plot w/o axes etc.
  theme(plot.margin = unit(c(-0,0,1,0), "cm"),
        aspect.ratio = 1)
panel_A
目录
相关文章
|
编解码 数据可视化 数据挖掘
R语言之基础绘图
R语言之基础绘图
327 0
|
数据可视化
R语言绘图教程丨Nature论文都在用的多组比较箱线图,自动计算显著性并标注,附带误差线
R语言绘图教程丨Nature论文都在用的多组比较箱线图,自动计算显著性并标注,附带误差线
R语言笔记丨绘图基础知识:饼图、条形图
R语言笔记丨绘图基础知识:饼图、条形图
R语言绘图相关函数(含实例)
R语言绘图相关函数(含实例)
271 0
|
机器学习/深度学习 数据可视化 数据挖掘
数据分享|R语言对论文作者研究机构、知识单元地理空间数据可视化
数据分享|R语言对论文作者研究机构、知识单元地理空间数据可视化
|
机器学习/深度学习 XML 自然语言处理
R语言LDA、CTM主题模型、RJAGS 吉布斯GIBBS采样文本挖掘分析论文摘要、通讯社数据
R语言LDA、CTM主题模型、RJAGS 吉布斯GIBBS采样文本挖掘分析论文摘要、通讯社数据
|
编译器
R语言JAGS贝叶斯回归模型分析博士生延期毕业完成论文时间
R语言JAGS贝叶斯回归模型分析博士生延期毕业完成论文时间
|
数据格式
基于 R 语言的绘图技巧汇总
基于 R 语言的绘图技巧汇总
156 1
|
数据可视化
基于 R 语言的科研论文绘图技巧详解(5)
基于 R 语言的科研论文绘图技巧详解(5)
271 0
基于 R 语言的科研论文绘图技巧详解(5)
|
存储 Go
速绘丨GO富集气泡图绘制方法,利用R语言ggplot2包快速绘制,完整脚本可重复绘图
速绘丨GO富集气泡图绘制方法,利用R语言ggplot2包快速绘制,完整脚本可重复绘图