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() 函数来设置. 主要有四种类型

  1. element_text(): Since the title, subtitle and captions are textual items
  2. element_line(): Likewise element_line() is use to modify line based components such as the axis lines, major and minor grid lines, etc.
  3. element_rect(): Modifies rectangle components such as plot and panel background.
  4. 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 (fillsizecolshape 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

 

posted @   icydengyw  阅读(938)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
点击右上角即可分享
微信分享提示