查看原文
其他

复现sci顶刊中的画中画(局部细节放大)

庄闪闪 庄闪闪的R语言手册 2023-08-11

点击下方公众号,回复资料分享,收获惊喜

简介

小编在撰写学术论文时,出现以下问题:图形重叠导致看不清细节。此时,可以通过放大图形中的局部位置。

图一:来自Wu, X., T. Huang and J. Liu (2023). "Common-Stochastic-Effects-Induced Multivariate Degradation Process with Temporal Dependencies in Degradation Characteristic and Unit Dimensions." Reliability Engineering & System Safety.

这种图在工业工程方向的顶级期刊中经常看到。本文小编将给出几种 R 中绘制局部细节放大图的方法。

注意:小编搜到过 matlab 和 Origin 绘制局部细节放大图的文章。但是很少看到有人写 R 相关的教程。

初级版本

这章节给出利用 ggplot[1] 包绘制模拟数据的线性图。下一章节将会介绍两种细节放大方法。

模拟数据产生

这里以一个模拟数据作为例子,读者可以根据自身数据情况进行替换。

# 生成模拟数据
com_battery = data.frame("Time" = 1:30,"True" = cumsum(abs(rnorm(30,2,0.4))),
                          "Proposed" = cumsum(abs(rnorm(30,2,0.5))),
                          "Linear" = cumsum(abs(rnorm(30,2,0.4))), 
                          "Power" = cumsum(abs(rnorm(30,2,0.1))),
                          "Exp" = cumsum(abs(rnorm(30,2,0.3))))

基础绘图

以时间作为 x 轴,各个模型拟合/预测值作为 y 轴。绘制出不同方法的拟合/预测对比图。

library(ggplot2)
library(tidyverse)
# 基础绘图
cols <- c("black","#85BA8F""#A3C8DC","#349839","#EA5D2D","#EABB77","#F09594")
p = com_battery %>% pivot_longer(cols = !Time, names_to = "Model", values_to = "Value") %>%
  mutate(Model = factor(Model, levels = c("True""Proposed""Linear","Power","Exp"))) %>% 
  ggplot(aes(Time,Value,col = Model,shape = Model)) + 
  geom_line() + geom_point(size=1.5,alpha=0.8) + 
  scale_color_manual(values = cols) +
  theme_bw() + theme(panel.grid = element_blank()) + #,legend.title=element_text(size=12), legend.text=element_text(size=11) +
  xlab("Time") + ylab("Rate(%)")
不同方法的拟合/预测对比图

可以看到,各个方法的拟合/预测结果非常接近。此时,可以通过放大局部细节来突出某个模型的优越性。

ggforce 包

ggforce[2] 包中的 facet_zoom() 可以通过一行代码实现局部细节放大的效果。官网[3]给出了各个参数的细节以及示例。

这里假设我们想对 xlim = c(18, 24),ylim = c(40, 43) 范围内的数据进行放大。只需要使用以下代码即可,其中 zoom.size = 0.4表示放大后的图形大小占比整个图的比例。

library(ggforce) 
p + facet_zoom(xlim = c(1824),ylim = c(4043), zoom.size = 0.4)

注意:当然还有其他几个参数可以调整,这里不做过多介绍。

如果你觉得这个图已经满足要求,并且美观程度还不错的话。那你就随意使用吧~但对于小编而言,这里的灰色框太奇怪了(不会改😭),而且整个构造也很突兀。

所以小编打算直接基于 ggplot 包的思想自己添加内容,并通过 patchwork[4] 包对图进行合并,复现出类似图一的效果。

patchwork 包

基于 ggplot 包,我们再绘制一幅需要局部放大的图,只需在 xlim()ylim() 上做文章,并去除标签和图例。

ppp = p + xlim(5,10) + ylim(10,20) + theme(legend.position = 'none') +
  xlab("") + ylab("")

之后将该图放到原图的合适位置即可,可以使用 patchwork 包中的 inset_element() 实现该功能。

注意:也可以使用cowplot[5]包进行图形合并。相关推文见:合并多幅图形利用 cowplot 包快速对齐图片

library(patchwork)
p + inset_element(ppp, 0.010.60.60.95, on_top = TRUE)

此时,基本完成了我们的要求,接下来进行一些细节处理:添加选择放大位置的框,添加指向箭头,修改图例位置等(注释在代码后)。

p +   
  geom_rect(aes(xmin = 5, xmax = 10, ymin = 10, ymax = 20),
            fill = "transparent", color = "black", alpha = 0
            linetype = "dashed", linewidth =0.2) + #添加选择放大位置的框
  theme(legend.position = c(0.9,.2),legend.background = element_rect(fill = 'white', colour = 'black')) + #修改图例位置
  geom_segment(aes(x = 7, xend = 10, y = 20, yend = 38.3), 
               col = "gray60", linewidth =0.2,linetype = "dashed",
               arrow = arrow(length = unit(0.2"cm"), type = "closed")) + # 添加指向箭头
  inset_element(ppp, 0.010.60.60.95, on_top = TRUE)

小编有话说

  • 模拟数据绘制出的效果可能不是很好,本文主要是给出 2 种绘制局部细节的方法供大家参考。这是小编平常科研中出现的一种画图需求,防止后续还会使用类似图形,所以在这做个记录也分享给大家。

  • 小编使用过 matlab 进行绘制这种图形,发现 matlab 可以互动式选择放大位置以及展示位置,非常方便。不知道这种功能是否可以借鉴到 R 中?

  • 如果有更好的方法欢迎读者们评论留言。也欢迎大家一键三连~

注意:本文所有代码已经上传至 Github[6] 中,欢迎下载使用。

参考资料

[1]

ggplot: https://ggplot2.tidyverse.org/

[2]

ggforce: https://ggforce.data-imaginist.com/

[3]

官网: https://ggforce.data-imaginist.com/reference/facet_zoom.html

[4]

patchwork: https://patchwork.data-imaginist.com/

[5]

cowplot: https://cran.r-project.org/web/packages/cowplot/vignettes/introduction.html

[6]

Github: https://github.com/liangliangzhuang/R_example

相关推文指南

cowplot包,ggplot2图形排版R包


使用 ggpubr 包制图


使用 ggcharts 高亮部分内容


使用 ggTimeSeries 包构建日历图


基于 ggdensity 包的等高线绘制


贝叶斯 RStan 包入门教程


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存