R:ggplot2数据可视化——进阶(2)
Part 2: Customizing the Look and Feel,
更高级的自定义化,比如说操作图例、注记、多图布局等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # 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()修饰
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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()
1 2 3 4 5 6 7 8 9 | 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()
1 2 3 4 5 6 7 8 9 10 | 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()
函数
1 2 3 4 5 6 7 8 9 10 | 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
实参改变颜色
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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()
1 2 3 4 5 6 7 8 9 10 | 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()
函数设置
1 2 3 4 5 6 7 8 9 10 11 12 | 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
指图例内的铰接点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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包为点添加文本或者标签 因为不会遮盖点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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()
1 2 3 4 5 6 7 8 9 10 | 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 () |
逆转坐标轴的范围顺序
1 2 3 4 5 6 7 8 9 10 | 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 切面:在一个图形中画多图
1 2 3 4 5 6 7 8 9 10 | 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'
解除约束 但是这样难以比较不同组之间的差异
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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
不能选择行数与列数
1 2 3 4 5 6 7 8 9 10 11 12 | 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) |
把这些图放到一个面板中
1 2 3 | # Draw Multiple plots in same figure. library (gridExtra) gridExtra:: grid.arrange (g1, g2, ncol=2) |
6 修改背景 主要次要坐标轴
改变背景
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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" ) |
删除主要次要格网 改变边界 轴标题 文本和刻度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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" ) |
在背景中添加图片
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示