R:ggplot2数据可视化——进阶(2)
Part 2: Customizing the Look and Feel,
更高级的自定义化,比如说操作图例、注记、多图布局等
# Setup options(scipen=999) library(ggplot2) data("midwest", package = "ggplot2") theme_set(theme_bw()) # midwest <- read.csv("http://goo.gl/G1K41K") # bkup data source # Add plot components -------------------------------- gg <- ggplot(midwest, aes(x=area, y=poptotal)) + geom_point(aes(col=state, size=popdensity)) + geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest") # Call plot ------------------------------------------ plot(gg)
传递给 theme()
的参数要求使用特定的 element_type()
函数来设置. 主要有四种类型
element_text()
: Since the title, subtitle and captions are textual itemselement_line()
: Likewiseelement_line()
is use to modify line based components such as the axis lines, major and minor grid lines, etc.element_rect()
: Modifies rectangle components such as plot and panel background.element_blank()
: Turns off displaying the theme item.清除主题展示
1 添加图形和轴标题
theme()
函数接受四个 element_type()
函数之一作为实参 由于标题是文本 使用element_text()修饰
library(ggplot2)
# Base Plot
gg <- ggplot(midwest, aes(x=area, y=poptotal)) +
geom_point(aes(col=state, size=popdensity)) +
geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) +
labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest")
# Modify theme components -------------------------------------------
gg + theme(plot.title=element_text(size=20,
face="bold",
family="American Typewriter",
color="tomato",
hjust=0.5,
lineheight=1.2), # title
plot.subtitle=element_text(size=15,
family="American Typewriter",
face="bold",
hjust=0.5), # subtitle
plot.caption=element_text(size=15), # caption
axis.title.x=element_text(vjust=10,
size=15), # X axis title
axis.title.y=element_text(size=15), # Y axis title
axis.text.x=element_text(size=10,
angle = 30,
vjust=.5), # X axis text
axis.text.y=element_text(size=10)) # Y axis text
vjust
, controls the vertical spacing between title (or label) and plot. 行距hjust
, controls the horizontal spacing. Setting it to 0.5 centers the title. 间距family
, 字体face
, sets the font face (“plain”, “italic”, “bold”, “bold.italic”)
?theme
2 修改图例
aesthetics are static, a legend is not drawn by default.
aesthetics (fill
, size
, col
, shape
or stroke
) base on another column, as in geom_point(aes(col=state, size=popdensity))
, a legend is automatically drawn.
改变标题
Method 1: Using labs()
library(ggplot2) # Base Plot gg <- ggplot(midwest, aes(x=area, y=poptotal)) + geom_point(aes(col=state, size=popdensity)) + geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest") gg + labs(color="State", size="Density") # modify legend title
Method 2: Using guides()
library(ggplot2) # Base Plot gg <- ggplot(midwest, aes(x=area, y=poptotal)) + geom_point(aes(col=state, size=popdensity)) + geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest") gg <- gg + guides(color=guide_legend("State"), size=guide_legend("Density")) # modify legend title plot(gg)
Method 3: Using scale_aesthetic_vartype()
format
scale_aestheic_vartype()
可以关闭指定变量的图例,其余保持不变 通过设置 guide=FALSE
基于连续变量的点的大小的图例, 使用 scale_size_continuous()
函数
library(ggplot2)
# Base Plot
gg <- ggplot(midwest, aes(x=area, y=poptotal)) +
geom_point(aes(col=state, size=popdensity)) +
geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) +
labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest")
# Modify Legend
gg + scale_color_discrete(name="State") + scale_size_continuous(name = "Density", guide = FALSE) # turn off legend for size
改变图例标签和点的颜色(针对不同类型)
使用对应的 scale_aesthetic_manual()
函数 新的图例标签作为一个字符向量 (labels
argument)
通过 values
实参改变颜色
library(ggplot2) # Base Plot gg <- ggplot(midwest, aes(x=area, y=poptotal)) + geom_point(aes(col=state, size=popdensity)) + geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest") gg + scale_color_manual(name="State", labels = c("Illinois", "Indiana", "Michigan", "Ohio", "Wisconsin"), #可以改变图例标签的顺序 values = c("IL"="blue", "IN"="red", "MI"="green", "OH"="brown", "WI"="orange"))
改变图例的顺序
guides()
library(ggplot2) # Base Plot gg <- ggplot(midwest, aes(x=area, y=poptotal)) + geom_point(aes(col=state, size=popdensity)) + geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest") gg + guides(colour = guide_legend(order = 1), size = guide_legend(order = 2))
改变图例标题 文本 背景的样式
图例的 key 是一个像元素的图形 , 使用 element_rect()
函数设置
library(ggplot2) # Base Plot gg <- ggplot(midwest, aes(x=area, y=poptotal)) + geom_point(aes(col=state, size=popdensity)) + geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest") gg + theme(legend.title = element_text(size=12, color = "firebrick"), legend.text = element_text(size=10), legend.key=element_rect(fill='springgreen')) + guides(colour = guide_legend(override.aes = list(size=2, stroke=1.5)))
删除图例和改变图例位置
可以使用 theme()
函数设置图例的位置 如果想把图例放在图形内部,可以使用 legend.justification 调整图例的铰接点
legend.position 是图例在图形中的坐标 其中
(0,0)是左下
(1,1)
是右上 legend.justification
指图例内的铰接点
library(ggplot2) # Base Plot gg <- ggplot(midwest, aes(x=area, y=poptotal)) + geom_point(aes(col=state, size=popdensity)) + geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest") # No legend -------------------------------------------------- gg + theme(legend.position="None") + labs(subtitle="No Legend") # Legend to the left ----------------------------------------- gg + theme(legend.position="left") + labs(subtitle="Legend on the Left") # legend at the bottom and horizontal ------------------------ gg + theme(legend.position="bottom", legend.box = "horizontal") + labs(subtitle="Legend at Bottom") # legend at bottom-right, inside the plot -------------------- gg + theme(legend.title = element_text(size=12, color = "salmon", face="bold"), legend.justification=c(1,0), legend.position=c(0.95, 0.05), legend.background = element_blank(), legend.key = element_blank()) + labs(subtitle="Legend: Bottom-Right Inside the Plot") # legend at top-left, inside the plot ------------------------- gg + theme(legend.title = element_text(size=12, color = "salmon", face="bold"), legend.justification=c(0,1), legend.position=c(0.05, 0.95), legend.background = element_blank(), legend.key = element_blank()) + labs(subtitle="Legend: Top-Left Inside the Plot")
添加文本 标签
对人口数超过 300K的县标记 首先创建一个切出来符合条件的数据框 (midwest_sub
)
然后用这个数据框作为数据源去画 geom_text
和 geom_label
推荐使用ggrepel包为点添加文本或者标签 因为不会遮盖点
library(ggplot2) # Filter required rows. midwest_sub <- midwest[midwest$poptotal > 300000, ] midwest_sub$large_county <- ifelse(midwest_sub$poptotal > 300000, midwest_sub$county, "") # Base Plot gg <- ggplot(midwest, aes(x=area, y=poptotal)) + geom_point(aes(col=state, size=popdensity)) + geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest") # Plot text and label ------------------------------------------------------ gg + geom_text(aes(label=large_county), size=2, data=midwest_sub) + labs(subtitle="With ggplot2::geom_text") + theme(legend.position = "None") # text 设置data参量 gg + geom_label(aes(label=large_county), size=2, data=midwest_sub, alpha=0.25) + labs(subtitle="With ggplot2::geom_label") + theme(legend.position = "None") # label 是有外边框的 # Plot text and label that REPELS eachother (using ggrepel pkg) ------------ library(ggrepel) gg + geom_text_repel(aes(label=large_county), size=2, data=midwest_sub) + labs(subtitle="With ggrepel::geom_text_repel") + theme(legend.position = "None") # text gg + geom_label_repel(aes(label=large_county), size=2, data=midwest_sub) + labs(subtitle="With ggrepel::geom_label_repel") + theme(legend.position = "None") # label
添加注记
使用 annotation_custom()
函数 需要一个 grob
作为参数
创建一个包含你想展示的文本的grob
library(ggplot2) # Base Plot gg <- ggplot(midwest, aes(x=area, y=poptotal)) + geom_point(aes(col=state, size=popdensity)) + geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest") # Define and add annotation ------------------------------------- library(grid) my_text <- "This text is at x=0.7 and y=0.8!" #文本 my_grob = grid.text(my_text, x=0.7, y=0.8, gp=gpar(col="firebrick", fontsize=14, fontface="bold")) #文本位置 样式 gg + annotation_custom(my_grob)
4 翻转x y轴
交换x y轴
coord_flip()
library(ggplot2) # Base Plot gg <- ggplot(midwest, aes(x=area, y=poptotal)) + geom_point(aes(col=state, size=popdensity)) + geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest", subtitle="X and Y axis Flipped") + theme(legend.position = "None") # Flip the X and Y axis ------------------------------------------------- gg + coord_flip()
逆转坐标轴的范围顺序
library(ggplot2) # Base Plot gg <- ggplot(midwest, aes(x=area, y=poptotal)) + geom_point(aes(col=state, size=popdensity)) + geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest", subtitle="Axis Scales Reversed") + theme(legend.position = "None") # Reverse the X and Y Axis --------------------------- gg + scale_x_reverse() + scale_y_reverse()
5 切面:在一个图形中画多图
library(ggplot2) data(mpg, package="ggplot2") # load data # mpg <- read.csv("http://goo.gl/uEeRGu") # alt data source g <- ggplot(mpg, aes(x=displ, y=hwy)) + geom_point() + labs(title="hwy vs displ", caption = "Source: mpg") + geom_smooth(method="lm", se=FALSE) + theme_bw() # apply bw theme plot(g)
我们得到一个简单的 highway mileage (hwy)
和 engine displacement (displ)
的图,但是如果想研究不同类型车辆这两个变量之间的关系呢?
Facet Wrap
所有的图形在x和y轴的缩放比例默认相同 可以通过设置 scales='free'
解除约束 但是这样难以比较不同组之间的差异
library(ggplot2) # Base Plot g <- ggplot(mpg, aes(x=displ, y=hwy)) + geom_point() + geom_smooth(method="lm", se=FALSE) + theme_bw() # apply bw theme # Facet wrap with common scales g + facet_wrap( ~ class, nrow=3) + labs(title="hwy vs displ", caption = "Source: mpg", subtitle="Ggplot2 - Faceting - Multiple plots in one figure") # Shared scales # Facet wrap with free scales g + facet_wrap( ~ class, scales = "free") + labs(title="hwy vs displ", caption = "Source: mpg", subtitle="Ggplot2 - Faceting - Multiple plots in one figure with free scales") # Scales free
Facet Grid
facet_grid()
用来把一个大图按照不同种类拆分成许多小图 将一个 formula作为主要参数 ~
左边构成行 而~右边构成列
标题行会占用很多空间 facet_grid()
会清理这些标题 facet_grid
不能选择行数与列数
library(ggplot2) # Base Plot g <- ggplot(mpg, aes(x=displ, y=hwy)) + geom_point() + labs(title="hwy vs displ", caption = "Source: mpg", subtitle="Ggplot2 - Faceting - Multiple plots in one figure") + geom_smooth(method="lm", se=FALSE) + theme_bw() # apply bw theme # Add Facet Grid g1 <- g + facet_grid(manufacturer ~ class) # manufacturer in rows and class in columns plot(g1)
把这些图放到一个面板中
# Draw Multiple plots in same figure. library(gridExtra) gridExtra::grid.arrange(g1, g2, ncol=2)
6 修改背景 主要次要坐标轴
改变背景
library(ggplot2) # Base Plot g <- ggplot(mpg, aes(x=displ, y=hwy)) + geom_point() + geom_smooth(method="lm", se=FALSE) + theme_bw() # apply bw theme # Change Plot Background elements ----------------------------------- g + theme(panel.background = element_rect(fill = 'khaki'), panel.grid.major = element_line(colour = "burlywood", size=1.5), panel.grid.minor = element_line(colour = "tomato", size=.25, linetype = "dashed"), panel.border = element_blank(), axis.line.x = element_line(colour = "darkorange", size=1.5, lineend = "butt"), axis.line.y = element_line(colour = "darkorange", size=1.5)) + labs(title="Modified Background", subtitle="How to Change Major and Minor grid, Axis Lines, No Border") # Change Plot Margins ----------------------------------------------- g + theme(plot.background=element_rect(fill="salmon"), plot.margin = unit(c(2, 2, 1, 1), "cm")) + # top, right, bottom, left labs(title="Modified Background", subtitle="How to Change Plot Margin")
删除主要次要格网 改变边界 轴标题 文本和刻度
library(ggplot2) # Base Plot g <- ggplot(mpg, aes(x=displ, y=hwy)) + geom_point() + geom_smooth(method="lm", se=FALSE) + theme_bw() # apply bw theme g + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.border = element_blank(), axis.title = element_blank(), axis.text = element_blank(), axis.ticks = element_blank()) + labs(title="Modified Background", subtitle="How to remove major and minor axis grid, border, axis title, text and ticks")
在背景中添加图片
library(ggplot2) library(grid) library(png) img <- png::readPNG("screenshots/Rlogo.png") # source: https://www.r-project.org/ g_pic <- rasterGrob(img, interpolate=TRUE) # Base Plot g <- ggplot(mpg, aes(x=displ, y=hwy)) + geom_point() + geom_smooth(method="lm", se=FALSE) + theme_bw() # apply bw theme g + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), plot.title = element_text(size = rel(1.5), face = "bold"), axis.ticks = element_blank()) + annotation_custom(g_pic, xmin=5, xmax=7, ymin=30, ymax=45)
Inheritance Structure of Theme Components
主题组分的继承结构
参考:
http://r-statistics.co/Complete-Ggplot2-Tutorial-Part2-Customizing-Theme-With-R-Code.html