R语言作图

基础作图

在数据分析过程中使用基础作图函数可以快速对数据进行概览,因此记住一些常用的基础作图函数是很有用的,比如plot、hist、boxplot、pie等函数。R的基础作图函数分为高阶作图函数和低阶作图函数,高阶作图函数能直接作出完整图形,而低阶作图函数只能在已有图形上添加内容。作图函数可以通过一些参数来进行作图效果的修饰:
main、sub、xlab、ylab参数依次分别设置主标题、副标题、x轴标题、y轴标题;
xlim、ylim分别限定横轴、纵轴的范围;
add参数确定是否作在前一个作图函数的结果上(默认add=FALSE);axes设定对否画出坐标轴和边框(默认axes=TRUE);asp参数设置y/x的比例。
另外还有一些参数可以通过par(……)来进行全局设置,有的可以直接放到作图函数中。如adj、bg、bty、cex(字体大小)、col(颜色)、font(字体风格)、las、lty(线的类型)、lwd(线的粗细)、mar、mfcol、mfrow、pch(点的类型)、ps、pty、tck、tcl、xaxt、yaxt、等等的,详情查看R的说明文档。
这些参数一般来说了解一下即可,通常只用基础作图快速概览,不需要对图进行精细调节。要做出精美的图,还是使用ggplot2更顺手和可控一些。

这里以一个身高数据作为示例。

SG <- read.delim("ftp://ftp.biolab.wang/data/height_inheritance.tsv", skip=1, fileEncoding="UTF-8")
head(SG, n=2)
##    序号 性别 年龄 身高 父亲身高 母亲身高
##  1    1   女   18  157      173      160
##  2    2   女   20  155      165      154

高阶作图函数

plot

plot(x, y)将x映射到横轴,y映射到y轴。可以通过type参数设置图的类型,type=“p”做散点图(point),type=“l”做折线图(line),type=“b”做折线图加点两者(both),type=“o”也是线加点,但线在点上,type=“c”也是线加点,但不显示点(也就是线线段之端点不衔接,而折线图线段端点是连接的),type=“h”做直方图(histogram),type=“s”做阶梯图(steps),数据映射到竖线的顶端,type=“S”也是阶梯图,但数据映射到竖线的下端,type=“n”表示不将图plot出来而只是把坐标系绘制出来;

plot(SG$父亲身高, SG$母亲身高, xlab="父亲身高", ylab="母亲身高", main="学生父亲身高与母亲身高对照图")

plot(1:10, 1:10, type="s", xlab="横轴标题", ylab="纵轴标题", main="type=\"s\"")
plot(1:10, 1:10, type="S", xlab="横轴标题", ylab="纵轴标题", main="type=\"S\"")

hist

hist(x)作直方图,

hist(SG$身高,  xlab="身高", ylab="人数", main="学生身高分布图")

barplot与pie

这里以展示男女性别比例或为例:

(NNBL <- table(SG$性别))
##  
##   男  女 
##  114 266 

barplot(x)作柱状图

barplot(NNBL, main="学生身高调查数据男女人数", col=c("cyan", "purple"))

pie(x)作饼图

pie(NNBL, main="学生身高调查数据男女比例图")

boxplot

boxplot作箱线图(盒形图),在数据分析的时候快速看数据分布情况很方便。boxplot(y~x),命令y映射到纵坐标,按照x来进行分组,x的值作为横坐标;boxplot(x),如果x为向量,则x映射到纵坐标,仅展示为一组,如果x是数据框或者矩阵,则每列一个个分组,列标题为横坐标。

boxplot(SG$身高~SG$性别, xlab=NULL, ylab="身高(cm)", col=c("blue", "pink"), main="学生身高调查")

boxplot(SG$身高, ylab="学生身高(cm)")

boxplot(SG[ , c("身高", "父亲身高", "母亲身高")], ylab="身高(cm)")

sunflowerplot

sunflowerplot(x, y)也是作散点图,但是具有相似坐标的点将会被做成一个带短线(像花一样)的点,由花瓣数代表数据点的个数。

set.seed(2020); X <- sample(1:10, 100, replace=TRUE)
set.seed(2022); Y <- sample(1:10, 100, replace=TRUE)
sunflowerplot(X, Y)

qqnorm与qqplot

qqnorm(x)作Q-Q图,横坐标为x在正态分布下期望的值,纵坐标为x。

qqnorm(SG$身高, sub="学生身高")

qqplot(x, y)作Q-Q图,横坐标为x,纵坐标为y。

qqplot((SG$父亲身高+SG$母亲身高)/2, SG$身高, xlab="Quantiles of Mid-parent Height (cm)", ylab="Quantiles of Adult-child Height (cm)", main="Q-Q Plot")

低阶作图函数

points(x, y)添加点; lines(x, y)添加线; text(x, y, labels, …)添加文字; legend(x, y, legend) 添加图例;axis(side, vect)添加坐标轴;

plot((SG$父亲身高+SG$母亲身高)/2, SG$身高, type="n", axes=FALSE, xlab="父母平均身高(cm)", ylab="学生身高(cm)")
text((SG$父亲身高+SG$母亲身高)/2, SG$身高, labels=SG$性别, cex=0.5, col=c(男="cyan", 女= "purple")[SG$性别])
axis(side=3)
axis(side=4)

arrows(x0, y0, x1, y1, angle= 30, code=2)添加箭头,code控制箭头位置点,code=1表示在点(x0, y0),code=2表示在(x1, y1),code=2表示两端都有箭头;angle则设置箭头边缘与轴线之间的角度。

abline(a, b)画一条斜率为b且截距为a的线,abline(h=y)画纵坐标为y的水平线,abline(v=x)画横坐标为x的竖线;


ggplot2

ggplot2简介

ggplot2是对作图语法的一种极好的实现,加上其强大的拓展, 是一个深受喜爱的数据可视化工具。可以参考其官方的介绍以及参考手册及更多。, 具备一定英文阅读能力的可以阅读ggplot2的作者Hadley Wickham的书ggplot2: Elegant Graphics for Data Analysis。我这尝试简要地介绍,以飨初学。
对于数据可视化需要考虑这些要素:用于作图的数据、数据的统计变换、图的类型、变量的视觉映射、映射的标尺、构图元素的位置调整、坐标系统、分面、图的主题风格等等各个方面。ggplot2的作图代码模版如下:

library(ggplot2)
ggplot(data = <数据框>) + 
  <几何函数>(
     mapping = aes(<视觉映射>),
     stat = <统计转换>, 
     position = <位置调整>
  ) +
  <标尺函数> +
  <坐标系统函数> +
  <分面函数> + 
  <主题风格函数>

data、mapping、stat、position、等等参数放在ggplot()函数里则控制为全局,设置到几何函数里则控制本几何函数。

数据 (data)

实际用于作图的数据(Data),其中包含了需要被展示出来的变量,每个变量一个维度。数据对象类型为数据框,每个变量一列。

几何对象 (geom)

几何对象(Geometric object),即图的类型,由geom_开头的几何函数定义。几何对象包括:散点图(geom_point)、折线图(geom_line)、柱状图(geom_bar)、直方图(geom_histogram)、盒形图(geom_boxplot)、密度曲线(geom_density)、……
几何对象分为个体几何对象(Individual geoms)和群体几何对象(Collective Geoms),个体几何对象为数据框中的每一行绘制一个图形对象,比如散点图(point geom)将,而群体几何对象将多个观测值展示到一个几何对象。
具体使用的时候,需要知道每个几个对象的适用场景,比如geom_bar默认情况下x和y只需要给的一个参数,默认对其进行计数统计(即stat=“count”)。比如这里使用柱状图展示两个班级的人数:

默认情况下如果同时给了x和y参数,就会报错:

ggplot(data=data.frame(班级=c("1班", "2班"), 人数=c(32, 23))) + 
    geom_bar(aes(x = 班级, y=人数))

这时候设置stat=“identity”则直接使用y作为纵坐标

ggplot(data=data.frame(班级=c("1班", "2班"), 人数=c(32, 23))) + 
    geom_bar(aes(x = 班级, y=人数), stat="identity")

视觉映射 (aes)

视觉映射(Aesthetic mappings) ,一个变量的值可以映射到不同的视觉属性,由几何函数中mapping参数定义。包括:横坐标(x)、纵坐标(y)、颜色(colour)、填充(fill)、透明度(alpha)、形状(shape)、大小(size)、 边框宽度(stroke)、线条类型(linetype)、分组(group)、…… 。不同几何对象能够映射的视觉属性有差异,而不同属性间的叠加也因属性值不同而会有不同。
初学者需要留意的是,这些视觉的元素放在aes函数里的效果是不同的。设定在aes里给mapping是以此作为一个变量进行映射,而放在aes函数外则是使用其值作为参数。比如自己运行如下两个作图代码试试看点的颜色有何不同,图片还有些什么差异:

ggplot() +  geom_point(mapping=aes(x=1:5, y=1:5, colour="blue"))
ggplot() +  geom_point(mapping=aes(x=1:5, y=1:5), colour="blue")

把“blue”放到aes里,是把它作为一个变量进行了映射,系统默认给映射到了红色,同时还会自动生成了图例。而把“blue”给了aes外边的colour,是设置了点的颜色为“bule”。

(dat <- data.frame(S1=1:5, S2=1:5, C1=letters[1:5], 
  C2=c("blue", "cyan", "green", "pink", "red")))
##    S1 S2 C1    C2
##  1  1  1  a  blue
##  2  2  2  b  cyan
##  3  3  3  c green
##  4  4  4  d  pink
##  5  5  5  e   red
 
ggplot(dat) + 
  geom_point(aes(x=S1, y=S2, color=C1)) +
  ggtitle("图1")
 
ggplot(dat) + 
  geom_point(aes(x=S1, y=S2, color=C2)) +
  ggtitle("图2")
 
ggplot(dat) + 
  geom_point(aes(x=S1, y=S2), color=dat$C2) +
  ggtitle("图3")

统计变换 (stat)

统计变换(Statistical transformations),对数据进行的转换,包括本身(stat_identity)、计数(stat_count)、……。统计变换和几何对象有一定的对应关系或者配合关系。
以stat_identity为例,设置可以可以是stat=“identity”或者stat=stat_identity()的方式,后者可以添加调整的参数,包括mapping指定变量映射以及geom指定几何对象。比如:

ggplot() + 
    stat_identity(
        mapping = aes(x=1:5, y=1:5), 
        geom    = "point")

效果等同于如下代码,都得到右图:

ggplot() + 
    geom_point(
        mapping=aes(x=1:5, y=1:5), 
        stat="identity")

位置调整 (position)

位置调整(Position adjustments),调整图形对象的位置。包括:原位(position_identity)、堆叠(position_stack)、比例堆叠(position_fill,堆叠且柱高归一)、分列(position_dodge)、加噪(position_jitter, 随机微量加减以避免点间重叠)、加噪分列(position_jitterdodge)、偏距(position_nudge,调整指定的距离,常用于是的文字偏离坐标一些)。
设置方式同样有:position=“stack”和position=position_stack()的方式,后者可以指定更多的参数。比如:

ggplot(data=data.frame(班级=c("1班", "1班", "2班", "2班"), 成绩=c("合格", "挂科", "合格", "挂科"), 人数=c(45, 5, 40, 6))) +
    geom_bar(mapping=aes(x=班级, y=人数, fill=成绩), 
             stat="identity",
             position=position_dodge(width=1)) +
    geom_text(mapping=aes(x=班级, y=人数, label=人数, group=成绩), 
             position=position_dodge(width=1), vjust=0)

这里通过设置同样的position参数,是的文字的标记正好出现在柱子的上方。试试看,把这两个width改得不一样会怎么样。这里对text不映射颜色,所以使用了group来进行分组,以便进行dodge排列,如果设置了colour映射则可省group。试试看,如果去掉了group参数会怎么样?

ggplot(data=data.frame(班级=c("1班", "1班", "2班", "2班"), 成绩=c("合格", "挂科", "合格", "挂科"), 人数=c(45, 5, 40, 6))) +
    geom_bar(mapping=aes(x=班级, y=人数, fill=成绩), 
             stat="identity",
             position="stack") +
    geom_text(mapping=aes(x=班级, y=人数, label=人数, group=成绩), 
             position=position_stack(vjust=0.5))

这里使用position_stack,在使用堆叠排列的时候,使得文字和柱子对应,使用vjust使之居中。vjust是纵向上的位置调整,默认值为1。还有一个reverse参数,可使用?position_stack查看了解详情。





标尺(scale)与尺标(guide)

标尺(Scales)控制数据到视觉属性的映射。通过scale_*_*序列函数(比如scale_x_continuous、scale_colour_discrete、……)来设置。

尺标(Guides)也就是坐标轴、图例(legend, 包括色带(colourbar)),使人们能够将视觉属性对应到数据。Guides是自动产生的,通过scale函数里的guide参数或者guides函数可以进行调整。

坐标系统(coord)

坐标系统(Coordinate systems)结合视觉对象的两个位置元素确定它在图上的位置,并且协同分面系统画坐标轴与面板背景。 标尺(Scales)控制坐标轴上的值以及从数据到位置的映射,而坐标系统则是实际将他们画出来,因此采用不同的坐标系统得到的图可能差异巨大。坐标系统包括:直角坐标(coord_cartesian)、极坐标(coord_polar)、地图坐标(coord_map)。直角坐标可以固定纵横比(coord_fixed)、横纵颠倒(coord_flip)、等等。

比如对右边这个散点图图,我们通过如下代码得到。使用scale和coord来截取其中一部分的效果不一样。

ggplot() + 
    geom_line(aes(x=1:10,y=sin(1:10)))

使用scale设置上下限,界限以外的被设成NA。

ggplot() + 
    geom_line(aes(x=1:10,y=sin(1:10))) +
    scale_x_continuous(limits = c(2.5, 7.5))

而使用coord来设置,则相当于只是截取了图片的这部分,而不影响数据。

ggplot() + 
    geom_line(aes(x=1:10,y=sin(1:10))) +
    coord_cartesian(xlim = c(2.5, 7.5))

分面(facet)

分面(Facet) 根据某些变量将数据分成子集,在针对各个子集分别作图并排列在一个页面,包括:网格型(facet_grid)和封面型(facet_wrap)。

主题 (theme)

主题(theme)控制非数据元素的外观,比如背景、网格线、坐标字体的颜色、图例字号的大小、图例的位置、……。通过? theme查看theme可以包括的参数,可调控性非常强,比如精确控制很坐标刻度值的属性可以通过axis.text.x参数进行调整。这些参数的值往往通过element_*函数来设定,元素的类型包括:文本(element_text)、线条(element_line)、矩形(element_rect)、空白(element_blank)。

另外也可以使用一些完整的预设主题,比如theme_grey()、theme_bw()、theme_classic()、theme_void()、……。尝试看看个个主题的风格是什么样子的。比如试试:

ggplot() + geom_point(mapping=aes(x=1:5, y=1:5), stat="identity") + theme_classic()

theme里可以设置的选项非常多,可以实现对图细节的精准、细致的调节。其中legend部分一些选参数所指项目看名称不是很直观,我这里示例如下,以便同学参考:

以上示例对应的theme设置为:

ggplot(dat=data.frame(X = LETTERS[1:3], XX = letters[1:3], Y=c(1, 2, 1)))        +
  geom_bar(aes(x = X, y = Y, fill = X), stat = "identity")                       +
  geom_line(aes(x = X, y = Y, group = 1))                                        +
  geom_point(aes(x = X, y = Y, shape = XX), size = 5)                            +
  scale_y_continuous(limits = c(0, 4), expand = c(0, 0))                         +
  xlab(NULL)                                                                     +
  ylab(NULL)                                                                     +
  theme_bw()                                                                     +
  theme(
    legend.box            = "horizontal",
    legend.box.background = element_rect(fill = "lightblue", color = "red", linewidth = 2),
    legend.box.margin     = margin(10, 10, 10, 10, unit = "mm"), 
    legend.box.spacing    = unit(35, unit = "mm"),
    legend.background     = element_rect(fill = "darkred", color = "green", linewidth = 2),
    legend.margin         = margin(10, 10, 10, 10, unit = "mm"), 
    legend.spacing.x      = unit(20, unit = "mm"),
    legend.key            = element_rect(fill = "lightgreen", color = "blue", linewidth = 2),
    legend.key.size       = unit(10, unit = "mm"),
    legend.key.spacing    = unit(10, unit = "mm"),
  )

中文字体

图片另存为pdf时,如果不指定字体,那么汉字无法显示。

pdf("test01.pdf")
plot(x=1, y=1, main="好", sub="I think that's OK")
##  Warning messages:
##  1: In title(...) : 'mbcsToSbcs'里转换'好'出错:<e5>代替了dot
##  2: In title(...) : 'mbcsToSbcs'里转换'好'出错:<a5>代替了dot
##  3: In title(...) : 'mbcsToSbcs'里转换'好'出错:<bd>代替了dot
##  4: In title(...) : 'mbcsToSbcs'里转换'好'出错:<e5>代替了dot
##  5: In title(...) : 'mbcsToSbcs'里转换'好'出错:<a5>代替了dot
##  6: In title(...) : 'mbcsToSbcs'里转换'好'出错:<bd>代替了dot
dev.off()
##  null device 
##            1 

使用GB1字体

这时候可以在pdf设备设置family参数

pdf("test02.pdf", family="GB1")
plot(x=1, y=1, main="好", sub="I think that's OK")
dev.off()
##  null device 
##            1 

也可以在绘图命令中指定family参数

pdf("test03.pdf")
plot(x=1, y=1, main="好", sub="I think that's OK", family= "GB1")
dev.off()
##  null device 
##            1 

可以看到,中文正常显示了,但是英文的显示效果似乎有些不太好。

使用showtext包

如果要使用其它的字体,可以使用showtext包,这个包把文本内容替换成图形,显示字体的效果,但是得到的pdf中的文字不再能够像文字一样被选择。
首先安装这个包:

install.packages("showtext")

最简单的是加载showtext包之后执行showtext_auto()命令,这样就能自动使用showtext来显示字体,如果不想用showtext了,可以用showtext_auto(FALSE)命令关闭。

library(showtext)
showtext_auto(TRUE)
pdf("test04.pdf")
plot(x=1, y=1, main="好", sub="I think that's OK")
dev.off()
##  null device 
##            1 

可以看到,这时候汉字和英文的显示效果都不错,但是这些字无法向文字一样被选择和复制。这里使用了showtext包内置的文泉驿微米黑(WenQuanYi Micro Hei family)字体。

使用指定的字体

showtext包使用sysfonts包的font_add函数添加的字体,加载showtext的时候,sysfonts包也会被加载。比如,我们这里添加宋体、黑体、楷体、隶书,叫做SHKL。

library(showtext)
showtext_auto(TRUE)
 
font_add(
  family     = "SHKL",
  regular    = "C:/Windows/Fonts/simsun.ttc",
  bold       = "C:/Windows/Fonts/simhei.ttf",
  italic     = "C:/Windows/Fonts/simkai.ttf",
  bolditalic =  "C:/Windows/Fonts/SIMLI.TTF"
)
 
pdf('test05.pdf', height=3, width=7)
plot(c(0,1), c(0.1,0.9), type='n', axes=FALSE, xlab='', ylab='')
text(0.5, 0.8, 'regular(正体) 对应 宋体', family="SHKL", font=1)
text(0.5, 0.6, 'bold(粗体) 对应 黑体', family="SHKL", font=2)
text(0.5, 0.4, 'italic(斜体) 对应 楷体', family="SHKL", font=3)
text(0.5, 0.2, 'bolditalic(粗斜体) 对应 隶书', family="SHKL", font=4)
dev.off()

library(showtext)
showtext_auto(TRUE)
 
font_add(family = "宋体", regular = "C:/Windows/Fonts/simsun.ttc")
font_add(family = "黑体", regular = "C:/Windows/Fonts/simhei.ttf")
font_add(family = "楷体", regular = "C:/Windows/Fonts/simkai.ttf")
font_add(family = "隶书", regular = "C:/Windows/Fonts/SIMLI.TTF")
 
pdf('test06.pdf', height=3, width=2)
plot(c(0,1), c(0.1,0.9), type='n', axes=FALSE, xlab='', ylab='')
text(0.5, 0.8, '这是宋体', family="宋体")
text(0.5, 0.6, '这是黑体', family="黑体")
text(0.5, 0.4, '这是楷体', family="楷体")
text(0.5, 0.2, '这是隶书', family="隶书")
dev.off()

.

图片排版

使用grid包的Viewports可以精确地控制图片在页面上的位置。
比如,我们现在有一组数据,记录一些学生的身高以及他们父母的身高。我们用这个数据做三个图,然后将三个图排布在一个页面。

URL <- "ftp://ftp.biolab.wang/data/height_inheritance.tsv";
dat <- read.delim(URL, skip=1, encoding="UTF-8")
library(grid)
library(ggplot2)
library(plyr)
library(ggpubr)
library(reshape)

图一,男女生身高均值比较:

dat01 <- ddply(dat, .(性别), summarize, 
  Mean=mean(身高), SD=sd(身高))
 
g1 <- 
ggplot(dat01) +
  geom_bar(aes(x=性别, y=Mean, fill=性别), 
    stat="identity") +
  geom_errorbar(aes(x=性别, y=Mean, 
      ymin=Mean-SD, ymax=Mean+SD, colour=性别),
    width=0.25, linewidth=2
  )+
  xlab(NULL) +
  ylab("Height") +
  scale_x_discrete(labels=c("Male", "Female")) +
  scale_y_continuous(limits=c(0, 200), 
    expand=c(0, 0)) +
  theme_classic() +
  theme(legend.position="none")
 
g1

图二,男生身高对父母平均身高的回归直线:

dat02 <- dat
dat02$父母平均身高 <- 
  (dat02$父亲身高 + dat02$母亲身高)/2
 
g2 <- 
ggplot(dat02[dat02$性别 == "男", ], 
    aes(x=父母平均身高, y=身高)) +
  geom_point() +
  geom_smooth(method='lm', formula= y~x, 
    se=FALSE)+
  ggpubr::stat_regline_equation(
    aes(label = paste("~", after_stat(eq.label), 
        after_stat(rr.label), sep = "~~~~")),
    formula = y~x, size=3,
    label.x.npc = 0.1, label.y.npc = 0.1
  ) +
  scale_x_continuous(limits=c(150, 175), 
    expand=c(0, 0), breaks=seq(150, 175, 5)) +
  scale_y_continuous(limits=c(150, 190),
    expand=c(0, 0), breaks=seq(150, 190, 5)) +
  xlab("Midparental Height") +
  ylab("Height") +
  theme_classic() +
  theme()  
 
g2

图三,亲代和子代身高分布图,区分性别:

dat03 <- dat[ , c("序号", "性别", "身高")]
dat03$代次 <- "子代"
dat04 <- dat[ , c("序号", "父亲身高", "母亲身高")]
names(dat04)[2:3] <- c("男", "女")
dat04 <- reshape::melt(dat04, id=1)
names(dat04)[2:3] <- c("性别", "身高")
dat04$代次 <- "亲代"
dat05 <- rbind(dat03, dat04)
 
g3 <- 
ggplot(dat05) +
  geom_boxplot(aes(x=性别, y=身高, colour=代次)) +
  scale_y_continuous(limits=c(140, 190),
    expand=c(0, 0), breaks=seq(140, 190, 5)) +
  scale_x_discrete(labels=c("Male", "Female")) +
  xlab(NULL) +
  ylab("Height") +
  theme_classic() +
  theme(legend.position=c(1, 1),
    legend.justification=c(1, 1),
    legend.box.background = element_blank(),
    legend.key = element_blank()
  )
 
g3

图片排版,将图二排在左边的2/3的页面,右边的1/3的页面上半部分排图一,下半部分排图三。效果如右图,代码如下:















# 打开一个新的页面,当前视窗为整个页面
grid.newpage()
 
# 定义一个子视窗,中点位于父视窗x方向1/3、y方向1/2,
# 宽是父视窗的2/3、高是父视窗的2/2
# 学习者如果不能直接想象到这个视窗区域,
# 可以自己拿笔画一画,以便明白
vp <- viewport(x=1/3, y=1/2, width=2/3, height=1)
# 进入相对于当前视窗的子视窗(且叫视窗A),
# 进入的视窗是其父视窗中vp指定的区域
pushViewport(vp)
  # pushViewport之后,当前视窗是视窗A,
  # 在当前视窗里进行作图,先将ggplot图形转为grob
  # grob即graph object,是能够被grid操作的图形对象
  grid.draw(ggplotGrob(g2))
  # 也可以在子视窗中添加文字,这里已经到了子视窗里,
  # x=0且y=1对应的就是左上角那个点,hjust和vjust调整对齐,
  # hjust=0就是x轴平方向以最左边对齐,
  # vjust=1就是y轴方向以最上边对齐,设为0.5则是中心点对齐,
  # 这里我们将这个文字放在当前视窗(A视窗)最左上方
  grid.text("A", x=0, y=1, hjust=0, vjust=1, 
    gp=gpar(fontsize=15, col="blue"))
# 做完图、添加了文字之后,回到父视窗,又回到了整个页面
upViewport()
 
# 然后进行下一个子图的绘制,再定义一个区域,然后一样的道理
vp <- viewport(x=5/6, y=3/4, width=1/3, height=1/2)
pushViewport(vp)
  grid.draw(ggplotGrob(g1))
  grid.text("B", x=0, y=1, hjust=0, vjust=1, 
    gp=gpar(fontsize=15, col="blue"))
upViewport()
 
vp <- viewport(x=5/6, y=1/4, width=1/3, height=1/2)
pushViewport(vp)
  grid.draw(ggplotGrob(g3))
  grid.text("C", x=0, y=1, hjust=0, vjust=1, 
    gp=gpar(fontsize=15, col="blue"))
upViewport()

PDF字体嵌入

cairo_pdf

使用cairo_pdf()得到的PDF文件就是已经嵌入了字体的。cairo_pdf()的用法与pdf()的一致,pdf()可能有更多的选项。但一般来说,cairo_pdf()也够用了。具体可以阅读这两个函数的使用手册。

? cairo_pdf
? pdf

embedFonts

使用grDevices包的embedFonts函数。需要先安装Ghostscript。

先告诉R Ghostscript的安装路径,这个根据自己实际来决定,比如我这里安装在D盘,使用的是64位的:

Sys.setenv(R_GSCMD="D:/Program/gs/gs9.18/bin/gswin64.exe")

然后直接使用embedFonts函数即可。

embedFonts(file="file_name.pdf", outfile = "new_file_name.pdf")

本网页已被访问12181次。