主题,是指图表背景色、面板背景色、坐标轴的宽度等附属元素的属性。图表是否美观、合理,在一定程度上取决于主题的设置。本节分为三个部分,首先介绍成套主题,其次介绍可在theme函数中直接修改的主题,最后介绍在theme函数中通过element_*系列函数修改的主题。
一、成套主题
主题设置涉及许多项目,有时我们只有对多个项目同时进行修改,才会看到理想的效果。比如,我们把背景色改为黑色,那么就应该同时把坐标轴标题之类的文字由默认的黑色改成浅色,这样才能让这些文字显示出来。为了简化操作,程序编写者设计了一些成套的主题。
library(ggplot2)
dat=read.csv("ip small.csv", row.names=1) # 前边的章节使用过的工业生产指数数据
p=ggplot(data=dat, aes(ID, Value, color=Area))+geom_line(size=1)
## ggplot2中的内置主题
p+theme_bw() # 黑白主题
p+theme_bw()+theme(panel.background=element_rect(fill="#DFCCFF")) #
使用成套主题后仍可以用后边会讲到的theme函数修改个别属性
p+theme_minimal() # 简单主题
p+theme_classic() # 经典主题
p+theme_void() # 去掉各种附属元素(我们以后将多次用到这个设置)
ggplot()+geom_blank(data=dat, aes(ID, Value)) # geom_blank是图层函数,而并非主题设置函数。笔者将其放在这里,是因为它能起到根据数据生成画布的作用。它的功能相当于用数据画一个散点图,只不过所有的点都是透明的
## ggthemes等R包也提供了一些有用的成套主题
# install.packages("ggthemes")
library(ggthemes)
p+theme_economist() # 《经济学人》风格
p+theme_par() # 模仿base作图系统
p+theme_stata() # 模仿Stata
p+theme_wsj() # 《华尔街日报》风格
二、theme函数:直接修改
用theme函数对主题进行修改的操作可分为两类。
dat=read.csv("ip big.csv", row.names=1) # 前边的章节使用过的工业生产指数数据
dat$Date=as.Date(dat$Date)
# 为进行示范我们有意生成两个图例
p=ggplot(dat)+geom_line(aes(Date, Value, color=Area, linetype= Area), size=1.2)+
scale_color_discrete(guide=guide_legend(title="legend 1"))+
scale_linetype_discrete(guide=guide_legend(title="legend 2"))
# 第1类:直接为参数指定一个值
p+theme(aspect.ratio=0.5)
# 第2类:用参数指定由element_*函数生成的值
p+theme(axis.text.x=element_text(angle=30, size=12))
下面我们首先介绍直接设定的方法。
总结起来,能够直接设置的项目有:
## legend.position:图例位置
# 选项为"none"、"bottom"、"top"、"left"、"right";也可以是长度为2的向量,此时给出的数值不是坐标值,而是图例的中心点在整个面板中的位置。水平位置和垂直位置均用0至1的数值来表示,因此,c(0.5, 0.5)就代表把图例画在面板中间
p+theme(legend.position="bottom")
p+theme(legend.position=c(0.5, 0.5)) # 整个图例的中心位于面板左边
## legend.direction:图例中格子的排列方向
# 选项为"horizontal"或"vertical"。当图表包含多个图例时,如果只想修改单个图例,请在guide_legend/colorbar里修改direction参数
p+theme(legend.position="bottom", legend.direction="vertical")
## legend.spacing:多个图例之间的距离
# 用unit函数进行设定,并选择适当的数值和"cm"、"inches"、"mm"等单位,以免把图例挤到图表外
p+theme(legend.position="bottom", legend.direction="vertical", legend.spacing=unit(3, "cm"))
## legend.spacing.x、legend.spacing.y:调整图例标题、格子或标尺、标签之间的距离
# 用unit函数调整
p+theme(legend.spacing.y=unit(10, "mm"), legend.spacing.x=unit(5,"mm")) # 此处的图例标题在其他部分的上边,用legend.spacing.y调整,标签在格子的右边,用legend.spacing.x调整
ggplot(dat)+geom_line(aes(ID, Value, color=Area))+
scale_color_discrete(guide=guide_legend(label.position="top"))+
theme(legend.spacing.y=unit(2, "mm")) # 此处的图例标题在标签上边、标签在格子上边,因此均用legend.spacing.y调整
## legend.key.size、legend.key.width、legend.key.height:同时修改格子的宽度和高度、修改宽度、仅修改高度
# 用unit函数调整
p+theme(legend.key.width=unit(2, "cm"), legend.key.height= unit(0.3, "cm"))
## legend.title.align、legend.text.align:图例标题和标签的对齐方式 # 取值为0(左)至1(右)之间的数值
p+theme(legend.title.align=0.5, legend.text.align=1)
## legend.justification:对整个图例的位置进行调整
# 当图例在左边或右边时,可选项为"center"、"top"或"bottom",当图例在上边或下边时,可选项为"center"、"left"或"right"
p+theme(legend.justification="top")
p+theme(legend.position="bottom", legend.direction="vertical", legend.justification="left")
# 取值也可为在0至1之间、长度为2的向量:当图例在左边或右边时,仅第二个数值有效,用于调整上下位置;当图例在上边或下边时,仅第一个数值起作用,用于调整左右位置
p+theme(legend.justification=c(999, 0))
p+theme(legend.position="bottom", legend.direction="vertical",legend.justification=c(0.2, 999))
## legend.box:多个图例的排列
# 当为"horizontal"时所有图例在同一行,当为"vertical"时在同一列
p+theme(legend.position="bottom", legend.box="vertical")
## legend.box.spacing:图例到绘图区的距离
# 用unit函数调整,正值使图例远离面板,负值使两者贴近,不过负值可能会使面板无法完整显示
p+theme(legend.box.spacing=unit(-2, "cm"))
## panel.ontop:是否把面板放在最上层
# 改变此设置唯一有意义的情境就是:用半透明从半透明的面板改变色调
p+theme(panel.background=element_rect(fill=scales::alpha("purple", 0.1)), panel.ontop=TRUE)
## axis.ticks.length:坐标轴刻度线的长度
# 用unit函数调整
p+theme(axis.ticks.length=unit(0.2, "cm"))
## plot.margin:画布边缘
# 用unit函数调整,需依次给出上、右、下、左的数值。注意:这个参数会修改整个图表的边缘,而不会修改各个分面的边缘(后边的章节会介绍分面的操作)
p+theme(legend.position="bottom", legend.box="vertical", plot. margin=unit(c(0, 0.5, 0, 0), "inches")) # 对边缘作调整常用于确保坐标轴标签可以完整显示
## plot.tag.position:标记的位置
# 选项为"top"、"topleft"(默认)、"topright"、"left"、"right"、"bottom"、"bottomleft"、"bottomright"这八个位置
p+labs(tag="Figure 1")+theme(plot.tag.position="left")
## aspect.ratio:面板的高宽比
# 请参阅本章第一节讲解coord_fixed函数的部分
## plot.title.position and plot.caption.position:标题(包含副标题)和注释的对齐位置
# 选项为"panel"(默认)或"plot"
p+labs(title="ABCDE", subtitle="abcde")+theme(plot.title.position="plot")
三、theme函数:用element_*函数修改
初学ggplot的读者可能会对下面要讲解的主题设置方式不太习惯。比如,我们要修改标题类文字的大小时,不能使用title.size=20之类的代码,而必须使用title=element_text(size=20)。在程序编写者看来,图表各种附属元素均可以被归为文字、线条、矩形三类。因此,调整背景色就相当于调整矩形的填充色,调整坐标轴的线形就相当于调整线条的线形。就此而言,用element_text、element_line和element_line函数进行调整反而让人感到更加明晰。
## 此类主题设置的书写形式是:
p+theme(panel.background=element_rect(fill="yellow"))
# 待修改的项目是panel.background(即面板背景色);对其进行修改相当于对矩形填充色进行修改,因此应使用element_rect;待修改的属性是填充色,因此参数为fill
# 注意:多数情况下,我们可按任意顺序调整主题,不过也有例外
p+theme_void()+theme(panel.background=element_rect(fill="yellow")) #正确:先去掉各种元素,再修改元素
p+theme(panel.background=element_rect(fill="yellow"))+theme_void() #错误:先修改元素,再去掉元素(这会导致上一步的修改无效)
# 用element_blank可删除我们指定的元素,而不会像theme_void那样删除多个附属元素。
p+theme(panel.background=element_blank(), axis.title=element_blank()) # 删除面板和坐标轴标题
1. element_text
用element_text修改的附属元素有:
●text:文字类元素。注意:并非文字的所有属性均可作一次性调整,比如,当使用text调整大小和颜色时,坐标轴标签的颜色就不会被改变。
●title:标题类文字。
●plot.title、plot.subtitle、plot.caption、plot.tag、legend.title:图表标题、副标题、注释、标记、图例标题。
●axis.title、axis.title.x、axis.title.x.top、axis.title.y、axis.title.y.right:坐标轴标题、X轴标题、上侧X轴标题、Y轴标题、右侧Y轴标题。
●axis.text、axis.text.x、axis.text.x.top、axis.text.y、axis.text.y.right:坐标轴标签、X轴标签、上侧X轴标签、Y轴标签、右侧Y轴标签。
●legend.text,图例标签。
■ 可修改的属性为:
●family:选项为:"sans"(默认), "serif", "mono"。
●face:粗体或斜体。1为普通,2为粗体,3为斜体,4为粗斜体。
●color:文字颜色。
●size:文字大小。
●angle,旋转角度。Y轴标题默认旋转90度。
●hjust、vjust:水平调整和垂直调整。取值越大文字越靠上(右),取值越小文字越靠下(左)。大于1或小于0的取值可能导致文字显示不完整。
●lineheight:行高。默认值为0.9。
dat=read.csv("ip small.csv", row.names=1) # 前边的章节使用过的工业生产指数数据
dat$Date=as.Date(dat$Date)
p=ggplot(dat)+geom_line(aes(Date, Value, color=Area), size=1.2)+
labs(title="Industrial Production Index", subtitle="2011/7 ~ 2013/6", caption="Using package ggplot2")
p+theme(text=element_text(color="orange", size=20)) # 所有文字类项目
p+theme(title=element_text(color="orange", size=20)) # 所有标题类文字
p+theme(axis.title.y=element_text(angle=0, vjust=0.5)) # 将Y轴标题改为水平放置,同时用vjust将其放到中部
p+labs(y="V\na\nl\nu\ne")+theme(axis.title.y=element_text (angle=0, vjust=0.5, lineheight=0.7)) # Y轴标题垂直排列
# 多项调整(www.xing528.com)
p+theme(
text=element_text(size=16),
axis.text.x=element_text(angle=30), # 旋转X轴标签
legend.text=element_text(face=4, color="red"), # 修改图例标签
plot.title=element_text(vjust=-12), # 使标题贴近甚至进入面板
plot.subtitle=element_text(vjust=-13),
plot.caption=element_text(hjust=0.5) # 调整注释的位置
)
2. element_line
用element_line修改的附属元素有:
●line:所有线条类元素。注意:并非文字的所有属性均可作一次性调整,比如,次要网格线的粗细不能用line设置。
●axis.ticks、axis.ticks.x、axis.ticks、axis.ticks.x.top、axis.ticks.y.right:坐标轴刻度线、X轴刻度线、Y轴刻度线、上侧X轴刻度线、右侧Y轴刻度线。
●axis.line、axis.line.x、axis.line.y、axis.line.x.top、axis.line.y.right:坐标轴线、X轴线、Y轴线、上侧X轴线、下侧Y轴线。
●panel.grid、panel.grid.major、panel.grid.minor、panel.grid.major.x、panel. grid.major.y、panel.grid.minor.x、panel.grid.minor.y:网格线、主要网格线、次要网格线,以及与X轴和Y轴相对应的主要、次要网格线。
可修改的属性为:color、size、linetype、lineend、arrow,请参阅前文对geom_line的说明。p+theme(
panel.grid=element_blank(),
axis.line=element_line(lineend="square", color="red", size=3, arrow=grid::arrow())
) # 默认状态下,ggplot并不显示坐标轴,仅当对坐标轴进行调整后,它才会显示出来p+theme(
panel.grid=element_line(linetype=2), # 所有网格线的线形
panel.grid.major.x=element_line(color="red"),
panel.grid.minor.y=element_line(color="green")
)
3. element_rect
用element_rect修改的附属元素为:
●plot.background:全图背景。
●panel.background:面板背景。注意:如果要给面板加边框,在此设置color="black"(或其他颜色)即可。
●legend.box.background、legend.background、legend.key:图例区(容纳多个图例的区域)背景、单个图例背景、图例格子背景。
■ 可修改的属性为:
●fill:填充色。如果不需要填充色,可设为NA。注意:此处没有alpha参数,如需使用半透明颜色,可用scales::alpha事先生成。
●size、linetype、color:轮廓线的粗线、线形、颜色。
## 请观察本例中涉及图例的修改
ggplot()+geom_point(aes(x=c("a", "b", "c"), y=1: 3, shape=c("a", "b","c"), color=1: 3))+
theme(
legend.box.background=element_rect(fill="blue", color="green", size=5),
legend.background=element_rect(fill="orange", color="yellow", size=2),
legend.key=element_rect(fill="purple", color="red", size=2)
)
# 综合使用各项主题设置(图3-3-1)
p+scale_color_manual(values=c("Machinery"="black", "Computer"="goldenrod1"), guide=guide_legend(override.aes=list(size=2)))+
theme(panel.background=element_blank(),
plot.background=element_rect(fill="steelblue3", color="steelblue3"),
legend.box.background=element_blank(),
legend.background=element_blank(),
legend.key=element_blank(),
text=element_text(color="palegreen1", size=20, family="serif"), plot.title=element_text(size=22),
axis.text=element_text(color="palegreen1"),
axis.title.y=element_text(angle=0, vjust=0.5),
panel.grid=element_blank(),
panel.grid.major.y=element_line(color="palegreen1", linetype=2),
axis.ticks=element_line(color="palegreen1")
)
图3-3-1 综合使用各项主题设置
#==========
# 练习:随机散点图
#==========
# 观察效果图(图3-3-2)可知,各组散点在靠近角落的地方较密集,而在靠近图表中间的位置较稀疏。这种效果是通过生成呈截断正态分布的数值实现的
library(truncnorm)
seed=1 # 设置随机种子
n=270 # 每组散点的个数
SD=3 # 正态分布的标准差
maxsize=17 # 点的最大尺寸
co=c("blue3", "green", "yellow", "red")
# 生成数据
set.seed(seed); x1=rtruncnorm(n, a=0, b=5, mean=0, sd=SD); seed= seed+1
set.seed(seed); y1=rtruncnorm(n, a=0, b=5, mean=0, sd=SD); seed= seed+1
set.seed(seed); s1=runif(n, 1, maxsize); seed=seed+1
set.seed(seed); x2=rtruncnorm(n, a=5, b=10, mean=10, sd=SD); seed= seed+1
set.seed(seed); y2=rtruncnorm(n, a=0, b=5, mean=0, sd=SD); seed= seed+1
set.seed(seed); s2=runif(n, 1, maxsize); seed=seed+1
set.seed(seed); x3=rtruncnorm(n, a=5, b=10, mean=10, sd=SD); seed= seed+1
set.seed(seed); y3=rtruncnorm(n, a=5, b=10, mean=10, sd=SD); seed= seed+1
set.seed(seed); s3=runif(n, 1, maxsize); seed=seed+1
set.seed(seed); x4=rtruncnorm(n, a=0, b=5, mean=0, sd=SD); seed= seed+1
set.seed(seed); y4=rtruncnorm(n, a=5, b=10, mean=10, sd=SD); seed= seed+1
set.seed(seed); s4=runif(n, 1, maxsize)
p=ggplot()+theme_void()+ # 删除附属元素
theme(aspect.ratio=1, plot.background=element_rect(fill="black", color=NA))+
coord_cartesian(xlim=c(0, 10), ylim=c(0, 10), expand=FALSE)+
geom_point(aes(x1, y1), alpha=0.2, size=s1, color=co[1])+
geom_point(aes(x2, y2), alpha=0.2, size=s2, color=co[2])+
geom_point(aes(x3, y3), alpha=0.2, size=s3, color=co[3])+
geom_point(aes(x4, y4), alpha=0.2, size=s4, color=co[4])
p+geom_text(aes(x=5, y=5, label="Science makes life colorful"),color="white", fontface=3, size=7, family="serif") # 后面的章节会讲到用于添加文字的geom_text函数
图3-3-2 随机散点图
#==========
# 练习:颠倒Y轴的图表
#==========
# 文件terror ym.csv记录了1968年至2009年期间,按月统计的世界各地恐怖袭击伤亡情况,我们用它来绘制一个颠倒Y轴的图表(图3-3-3)
library(reshape2)
dat=read.csv("terror ym.csv", row.names=1) # 课件中的文件
dat=dat[384: 503, ] # 只使用2000年至2009年的数据
dat=melt(dat, id.vars="Date", measure.vars=c("Fatalities", "Injuries"))
# 转化成ggplot接受的形式
dat$Date=as.Date(dat$Date) # 转化成Date对象以便使用scale_x_date
# 第一个年份显示四位数字,后边的只显示两位数字
pos=paste(2000: 2009, "-01-01", sep="")
true_lab=substr(2000: 2009, start=3, stop=4)
true_lab[1]="2000"
# 本例使用的geom_area用于绘制带阴影的曲线,后边的章节将对其进行详细介绍
p=ggplot(dat)+
geom_area(aes(x=Date, y=value, alpha=variable), fill="red", position=position_identity())+
scale_alpha_manual(values=c("Fatalities"=1, "Injuries"= 0.4))+
scale_y_reverse(name=NULL)+ # 颠倒Y轴
scale_x_date(name=NULL, breaks=as.Date(pos), labels=true_lab, position="top") # 将X轴放到顶部
p+theme_void()+
labs(title="Monthly Fatalities and Injuries of\n Terrorist Attacks 2000 ~ 2009\n")+
theme(
text=element_text(family="mono"),
axis.text=element_text(size=15, color="grey70"),
plot.title=element_text(color="grey70", size=18, hjust=1),
legend.title=element_blank(),
legend.text=element_text(color="white", size=14),
plot.background=element_rect(fill="grey15", color=NA),
plot.margin=unit(rep(4, 4), "mm"),
axis.ticks.x.top=element_line(color="grey30"),
axis.ticks.length=unit(2, "mm"),
panel.grid.major.y=element_line(color="grey30", linetype= 3),
legend.position="bottom"
)
图3-3-3 颠倒Y轴的图表
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。