> For the complete documentation index, see [llms.txt](https://peng-6.gitbook.io/ggplot-jian-ming-jiao-cheng/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://peng-6.gitbook.io/ggplot-jian-ming-jiao-cheng/jiao-cheng/04-ggplot2-san-bu-qu-zui-zhong-zhi-jin-jie-wei-cai-niao.md).

# 04 ggplot2三部曲最终之进阶为菜鸟

* Date : 2021-11-25\_Thu
* 微信公众号 : 北野茶缸子
* Tags : #R/R可视化 #R/R数据科学 #R/index/01
* 参考：<https://www.cedricscherer.com/2019/08/05/a-ggplot2-tutorial-for-beautiful-plotting-in-r/#prep> （挑选的翻译了全文，并结合了一些自己的经验）

因为我也并非逐帧翻译，所以我强烈建议你看完ggplot 的入门书籍之后，就自己手撕一下上面的教程。

## 开始之前

请直接加载`tidyverse` 套件。

这里使用数据：

```
chic <- readr::read_csv("https://raw.githubusercontent.com/Z3tt/R-Tutorials/master/ggplot2/chicago-nmmaps.csv")
```

ps: read\_csv 命令可以从网络读取文件。

了解一下该数据：

```
> glimpse(chic)
Rows: 1,461
Columns: 10
$ city     <chr> "chic", "chic", "chic", "chic", "chic", "chic", "chic", "ch…
$ date     <date> 1997-01-01, 1997-01-02, 1997-01-03, 1997-01-04, 1997-01-05…
$ death    <dbl> 137, 123, 127, 146, 102, 127, 116, 118, 148, 121, 110, 127,…
$ temp     <dbl> 36.0, 45.0, 40.0, 51.5, 27.0, 17.0, 16.0, 19.0, 26.0, 16.0,…
$ dewpoint <dbl> 37.500, 47.250, 38.000, 45.500, 11.250, 5.750, 7.000, 17.75…
$ pm10     <dbl> 13.052268, 41.948600, 27.041751, 25.072573, 15.343121, 9.36…
$ o3       <dbl> 5.659256, 5.525417, 6.288548, 7.537758, 20.760798, 14.94087…
$ time     <dbl> 3654, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662, 3663,…
$ season   <chr> "Winter", "Winter", "Winter", "Winter", "Winter", "Winter",…
$ year     <dbl> 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997,…
```

## 1. ggplot 的元素对象

这些元素对象并不都是必须的，但都对应着不同的元素： 但一般来说，data 和Geometries 是必须的，我们必须告诉ggplot 用什么数据，画什么图。

```
Data: The raw data that you want to plot.
Geometries geom_: The geometric shapes that will represent the data.
Aesthetics aes(): Aesthetics of the geometric and statistical objects, such as position, color, size, shape, and transparency
Scales scale_: Maps between the data and the aesthetic dimensions, such as data range to plot width or factor values to colors.
Statistical transformations stat_: Statistical summaries of the data, such as quantiles, fitted curves, and sums.
Coordinate system coord_: The transformation used for mapping data coordinates into the plane of the data rectangle.
Facets facet_: The arrangement of the data into a grid of plots.
Visual themes theme(): The overall visual defaults of a plot, such as background, grids, axes, default typeface, sizes and colors.
```

![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1617443712203-80b5978a-ecf9-419a-8016-128ad7139c0b.png#height=626\&id=bK6Mj\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1252\&originWidth=1540\&originalType=binary\&ratio=1\&size=290462\&status=done\&style=none\&width=770)

## 2. ggplot2 的几何对象

* 折线图

geom\_line 有参数group ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1617455777218-2d7195c4-a70f-4049-955f-6940cd2906e0.png#height=591\&id=kduoi\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1182\&originWidth=1570\&originalType=binary\&ratio=1\&size=165460\&status=done\&style=none\&width=785)

* 散点图

![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1617455788873-53bdc617-a4f0-4d09-b97b-45150d7aa4f4.png#height=592\&id=GvR9C\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1184\&originWidth=1590\&originalType=binary\&ratio=1\&size=232998\&status=done\&style=none\&width=795) ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1630069265292-b20eca22-dabb-4a6a-9408-b66c6b18034e.png#clientId=u319da315-095c-4\&from=paste\&height=528\&id=ua9824844\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1056\&originWidth=1606\&originalType=binary\&ratio=1\&size=137385\&status=done\&style=none\&taskId=uccfa01cf-f449-4c0a-a0e6-e4c6c0f0632\&width=803)

## 3. 映射

![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1596968178106-c98efac6-44f5-447a-b397-474328feba4e.png#height=435\&id=xDyeN\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=870\&originWidth=1054\&originalType=binary\&ratio=1\&size=291833\&status=done\&style=none\&width=527)

```r
group #分组
labels #标记
```

关于aes 相关参数可以直接为这些参数赋值为相关的变量，通过映射的方式，按照函数默认方式为它们赋值。

```r
ggplot(data = test)+
  geom_point(mapping = aes(x = Sepal.Length,
                           y = Petal.Length,
                           color = Species))
```

如果想要将以上的参数赋值为手动定义的内容，则需要将其抽出aes 函数内。

```r
ggplot(data = test)+
  geom_point(mapping = aes(x = Sepal.Length,
                           y = Petal.Length),
            color = "red")
```

### 手动设置与映射

![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1596968724101-7eab6508-6124-4fbf-8dc7-ab64076be402.png#height=667\&id=nBzwX\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1334\&originWidth=2444\&originalType=binary\&ratio=1\&size=1474740\&status=done\&style=none\&width=1222) 映射要有“领导思维”，直接将变量给对应的参数；手动设置则“精准定位”，该是什么就给参数设定什么。

### shape

具体的shape 有25个值。 ![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1596968627561-4933df28-5672-49df-b12c-40d8d783ab98.png#height=412\&id=kv1F1\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=823\&originWidth=1240\&originalType=binary\&ratio=1\&size=118133\&status=done\&style=none\&width=620)

### color/fill

为了区分图形的轮廓与内部颜色，分别使用color 与fill 对应：

```
ggplot(chic, aes(x = date, y = temp)) +
  geom_point(shape = 21, size = 2, stroke = 1,
             color = "#3cc08f", fill = "#c08f3c") +
  labs(x = "Year", y = "Temperature (°F)")
```

![](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618809343218-81b899c5-bd8a-495b-95ff-07d536cb0e85.png#height=480\&id=u0196c3fd\&margin=%5Bobject%20Object%5D\&originHeight=960\&originWidth=1344\&originalType=binary\&ratio=1\&status=done\&style=none\&width=672)

#### 分类变量颜色

如果我们想要给映射的颜色进行自定义，可以使用函数scale\_color\_manual ：

```
ga + scale_color_manual(values = c("dodgerblue4",
                                   "darkolivegreen4",
                                   "darkorchid3",
                                   "goldenrod1"))
```

![](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618809672255-988828ff-c0fa-47cb-a513-414d1e2b4c22.png#height=480\&id=u2304856c\&margin=%5Bobject%20Object%5D\&originHeight=960\&originWidth=1344\&originalType=binary\&ratio=1\&status=done\&style=none\&width=672)

或者也可以指定调色板：

```
# ga + scale_color_brewer(palette = "Set1")

library(ggthemes)
ga + scale_color_tableau()
```

![](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618809847060-42d40312-0874-4fcc-a1b7-6ce61cd18986.png#height=480\&id=ud173d66a\&margin=%5Bobject%20Object%5D\&originHeight=960\&originWidth=1344\&originalType=binary\&ratio=1\&status=done\&style=none\&width=672)

#### 处理连续性变量颜色

对于连续性变量，R 会自动进行识别，但我们并不能像分类变量一样直接指定颜色，我们可以通过函数scale\_color\_gradient 修改：

```
gb + scale_color_gradient(low = "darkkhaki",
                          high = "darkgreen")
```

![](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618820623086-3510d0db-08a6-4641-a54d-2afcdd7a0689.png#height=480\&id=uab0f1057\&margin=%5Bobject%20Object%5D\&originHeight=960\&originWidth=1344\&originalType=binary\&ratio=1\&status=done\&style=none\&width=672)

除此之外，我们还可以指定数值的中间变化点：

```
mid <- mean(chic$temp)  ## midpoint

gb + scale_color_gradient2(midpoint = mid)

# 也可以同时指定颜色
gb + scale_color_gradient2(midpoint = mid, low = "#dd8a0b",
                           mid = "grey92", high = "#32a676")
```

![](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618820664434-3679bf97-115e-4615-9352-7c5ee165e1e0.png#height=480\&id=udbe513ac\&margin=%5Bobject%20Object%5D\&originHeight=960\&originWidth=1344\&originalType=binary\&ratio=1\&status=done\&style=none\&width=672)

在新版本的ggplot 中，我们可以

#### 更多颜色的知识

这里有本关于颜色的pdf：<http://www.stat.columbia.edu/~tzheng/files/Rcolor.pdf>

对于颜色，我们也需要对应不同数据，选择好不同的类型： ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618809495644-24d0f6ff-5025-4b1f-9077-dea3298d7516.png#height=183\&id=u02f337ab\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=183\&originWidth=708\&originalType=binary\&ratio=1\&size=20684\&status=done\&style=none\&width=708)

关于颜色，可以参见我的专题：

## 4. 分面

我们常常能看到一些炫酷的分面的图片： ![](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618804386474-aa42b31c-ed60-47a2-8f74-1606644d5ae4.png#height=480\&id=u01bc0a1b\&margin=%5Bobject%20Object%5D\&originHeight=960\&originWidth=1344\&originalType=binary\&ratio=1\&status=done\&style=none\&width=672)

其实也就是在本来的x, y等映射之上，增加了分面的映射，我们不仅可以按照行也可以按照列做应映射，其中主要包括两个函数：`facet_wrap`，对单一变量映射，但可以调整分面后图片在每层与每列的数目；`facet_grid` ，可以接受两个变量映射。

### facetgrid()

![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1596968822972-4f134648-b218-49a5-a2f1-831d44c7d108.png#height=226\&id=M8Nfl\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=452\&originWidth=932\&originalType=binary\&ratio=1\&size=49339\&status=done\&style=none\&width=466) A 对应y 轴，B 对应x 轴：

```r
ggplot(mpg) + 
  geom_point(aes(displ,hwy,color=drv)) +
  facet_grid(drv ~ cyl)
```

![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597139116274-f3554c1b-1564-496b-8fbf-e5bb52746d39.png#height=586\&id=FP2AU\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1172\&originWidth=1150\&originalType=binary\&ratio=1\&size=161909\&status=done\&style=none\&width=575)

### facet\_warp()

facet\_grid 对多图形的分面显示不是特别友好，而facet\_warp() 则可以设定分面行与列的数目。

对比一下

```bash
ggplot(mpg) + 
  geom_point(aes(displ,hwy,color=drv)) +
  facet_grid(class~.)
```

![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597138380802-87472422-d4b9-44d9-8fec-8433a4a49d9d.png#height=579\&id=kBYQj\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1158\&originWidth=1170\&originalType=binary\&ratio=1\&size=149002\&status=done\&style=none\&width=585)

```bash
ggplot(mpg) + 
  geom_point(aes(displ,hwy,color=drv)) +
  facet_wrap(~class, ncol = 3)
```

## ![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597138499469-ba7b09ed-4303-476f-a321-93ce9c402e4c.png#height=583\&id=s3cFD\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1166\&originWidth=1166\&originalType=binary\&ratio=1\&size=145107\&status=done\&style=none\&width=583)

### warp与grid 的区别

warp 只能对一种变量进行分类（一个维度），因此如果对其使用两个变量，则其会罗列在一个维度。 ![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597138919494-72a5a31f-3230-4684-9d27-80de9c16542f.png#height=585\&id=ONeDw\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1170\&originWidth=1152\&originalType=binary\&ratio=1\&size=173584\&status=done\&style=none\&width=576) 但其相比grid 的优势在于，它可以自定义输出的分面的行与列数。

### 一些参数

* 自由的坐标轴

```
ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "orangered", alpha = .3) +
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) +
  labs(x = "Year", y = "Temperature (°F)") +
  facet_wrap(~ year, ncol = 2, scales = "free")
```

![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618805325032-0026c8e6-3788-4e4a-aaa8-ca16faf5a62d.png#height=334\&id=uabd92bc6\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=667\&originWidth=1280\&originalType=binary\&ratio=1\&size=86408\&status=done\&style=none\&width=640)

* 让wrap 接受两个变量

默认下，facet\_wrap 是无法同时接受两个变量的，否则会成这样： ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618805738097-f8a11815-5c09-4791-a959-33c56162bc7e.png#height=509\&id=uc752c643\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1017\&originWidth=1920\&originalType=binary\&ratio=1\&size=193926\&status=done\&style=none\&width=960) 相当于将两个变量，映射到一个边了。

我们可以修改scales 参数，让其稍微好看一些：

```
ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "orangered", alpha = .3) +
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) +
  labs(x = "Year", y = "Temperature (°F)") +
  facet_wrap(season ~ year, ncol = 4, scales = "free_x")
```

![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618806040563-9779544b-3906-4e8f-9f5f-94a564b9c5e0.png#height=339\&id=uf65bbb10\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=678\&originWidth=1280\&originalType=binary\&ratio=1\&size=88927\&status=done\&style=none\&width=640) 对于grid 我们也是可以使用scales 的。

## 5. 坐标轴

### 限定坐标区域

我们可以调整坐标轴大小：

```
scale_y_continuous(limits = c(0, 50)) 
# 限制数据范围，超出范围数据不显示
coord_cartesian(ylim = c(0, 50))
# 直接限制图的坐标
```

二者均是指定坐标轴范围，但存在一定的差别。 ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1617460238626-db3ded17-c017-4ac1-adbb-0150fa9218d4.png#height=550\&id=Jo3wl\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1100\&originWidth=1592\&originalType=binary\&ratio=1\&size=299571\&status=done\&style=none\&width=796)

下图更直观一些，`scale_y_continuous` 相当于还对数据进行了filter 的操作： ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1617460278851-d99cac03-fd8c-4ef7-9499-40e9d53e6356.png#height=552\&id=ut2hw\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1104\&originWidth=1556\&originalType=binary\&ratio=1\&size=152852\&status=done\&style=none\&width=778)

### 调整坐标比例

默认下，ggplot 会将长宽设定同样比例： ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1617460597527-33a96504-cca8-452a-b9f1-aef1b57375cb.png#height=678\&id=yNefe\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1356\&originWidth=1848\&originalType=binary\&ratio=1\&size=364476\&status=done\&style=none\&width=924) 但很明显，纵坐标的数值是高于横坐标的，我们可以修改一下：

```
ggplot(chic, aes(x = temp, y = temp + rnorm(nrow(chic), sd = 20))) +
  geom_point(color = "sienna") +
  labs(x = "Temperature (°F)", y = "Temperature (°F) + random noise") +
  xlim(c(0, 100)) + ylim(c(0, 150)) +
  coord_fixed()
```

![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1617460676940-f774954d-4efa-4705-81e3-df25a9c69e57.png#height=551\&id=Hbzob\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1102\&originWidth=844\&originalType=binary\&ratio=1\&size=184693\&status=done\&style=none\&width=422)

我们也可以自定义`coord_fixed` 函数中的`ratio` 参数，输出希望得到的比例，比如`coord_fixed(ratio = 1/5)`： ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1617460686793-60617ad7-cb5e-4996-b18d-b619b2564a07.png#height=307\&id=PBZDm\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=614\&originWidth=1584\&originalType=binary\&ratio=1\&size=167432\&status=done\&style=none\&width=792)

### 利用函数处理

这个通常可以用来批量对坐标上的标记进行处理：

```
ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") +
  labs(x = "Year", y = NULL) +
  scale_y_continuous(label = function(x) {return(paste(x, "Degrees Fahrenheit"))})
```

![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1617548689224-2dc166fa-5698-424d-b0b9-d4c2825b6371.png#height=480\&id=Jy0vx\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=960\&originWidth=1344\&originalType=binary\&ratio=1\&size=115079\&status=done\&style=none\&width=672)

### 其他参数

其他参数包括：

```
expand_limits(x = 0, y = 0)
# 强制锁定坐标轴初始位点
# 和 coord_cartesian(xlim = c(0, NA), ylim = c(0, NA)) 效果一致
coord_cartesian(clip = "off")
# 允许坐标画在坐标轴上
```

## 6. 主题

### 文本属性

通过`theme` 函数，我们可以修改一些主题中的元素。 比如通过labs 添加的文本，可以通过theme 修改其位置、大小、颜色等属性，包括：

```r
axis.title.x # x轴标题
axis.text # 坐标轴文本标记
axis.ticks # 坐标轴标记点
plot.subtitle # 亚标题
plot.caption # 注释
legend.title # 图例标题
legend.text # 图例文本
legend.background # 图例背景
legend.key # 图例标记背景
```

* element\_text

其中的参数有：

```r
vjust # 上下移动，正为下，负为下
hjust # 左右移动
lineheight # 也可以用来改变所在的高度，值越大越高，接近0 表示该文本与其他文本位置重合
size # 大小
# 大小可以利用rel 函数，如rel(1.5)，就表示增大到原先的1.5倍
angle # 偏转角度，默认为水平
margin = margin(t = 10)
# 图轴上移动
margin = margin(r = 10)
# 图轴右移动
margin = margin(10, 10, 10, 10)
## t r l b（trouble） 上右左下
face = "italic" # 字体
color = "firebrick" # 颜色
```

范例：

```r
ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") +
  labs(x = "Year", y = "Temperature (°F)") +
  theme(axis.title.x = element_text(margin = margin(t = 10), size = 15),
        axis.title.y = element_text(margin = margin(r = 10), size = 15))
```

![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1617457471874-3a364ae4-6d72-45e9-8e96-d439ef3eb217.png#height=561\&id=y97kh\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1122\&originWidth=1684\&originalType=binary\&ratio=1\&size=261138\&status=done\&style=none\&width=842)

* element\_blank()

直接取消文本：

```r
ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") +
  labs(x = "Year", y = "Temperature (°F)") +
  theme(axis.ticks.y = element_blank(),
        axis.text.y = element_blank())
```

![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1617457885531-fde59591-274f-4367-a621-918744d38e95.png#height=545\&id=FK4zg\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1090\&originWidth=1626\&originalType=binary\&ratio=1\&size=256027\&status=done\&style=none\&width=813) 光秃秃的了～ 其实也可以直接定义文本为空：

```r
ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") +
  labs(x = NULL, y = "")
```

但并不是所有文本都可以在labs 中被定义，比如图例的标题：

```r
ggplot(chic, aes(x = date, y = temp, color = season)) +
  geom_point() +
  labs(x = "Year", y = "Temperature (°F)") +
  theme(legend.title = element_blank())
```

### 文本位置

除了通过hjust 等调整，我们还可以使用参数`plot.xx.position`：

```r
g + theme(plot.title.position = "plot",
          plot.caption.position = "plot")
```

一般包括`plot` 与`panel` 两种。

对于legend，还有`"none"`，表示不显示图例：

```r
ggplot(chic, aes(x = date, y = temp)) +
  geom_point(aes(color = season)) +
  labs(x = "Year", y = "Temperature (°F)",
       title = "Temperatures in Chicago",
       subtitle = "Seasonal pattern of daily temperatures from 1997 to 2001",
       caption = "Data: NMMAPS",
       tag = "Fig. 1") + theme_classic() +
  theme(text = element_text(family = "gochi"), legend.position = "none") 
```

![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1617635030014-4d3fc404-0052-4ce0-9546-80e0260a45fb.png#height=697\&id=jBhrI\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1394\&originWidth=2094\&originalType=binary\&ratio=1\&size=324969\&status=done\&style=none\&width=1047)

关于图例的位置，在下一部分介绍。

### 和图例较劲

参见：

### 背景与画布

我们可以用ggplot 提供的自带主题来修改背景，比如我个人最喜欢的theme\_classic 就直接呈现一个白板，特别简洁。

当然我们也可以自定义背景。

包括的参数有：

```bash
panel.background # 画布
panel.border # 画布及画布边界
plot.background # 背景
```

* element\_rect

如果我们希望把背景颜色换一下，可以使用：

```bash
ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "#1D8565", size = 2) +
  labs(x = "Year", y = "Temperature (°F)") +
  theme(panel.background = element_rect(
    fill = "#64D2AA", color = "#64D2AA", size = 2)
  )
```

![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618410966455-9eadc428-4952-43b7-951a-2b46cf2acc59.png#height=480\&id=mxD1N\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=960\&originWidth=1344\&originalType=binary\&ratio=1\&size=126414\&status=done\&style=none\&width=672) panel.border ： ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618411225146-3855b229-65a6-429d-9d61-96a8458ba130.png#height=480\&id=MlEhG\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=960\&originWidth=1344\&originalType=binary\&ratio=1\&size=126687\&status=done\&style=none\&width=672) 画布不同于背景，背景指的是单纯的图像数据后面的内容：

```bash
ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") +
  labs(x = "Year", y = "Temperature (°F)") +
  theme(plot.background = element_rect(fill = "gray60",
                                       color = "gray30", size = 2))
```

![](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618489189907-b5fcc187-bbb9-4c7f-916d-d23af402ebf0.png#height=480\&id=ua7d98e0d\&margin=%5Bobject%20Object%5D\&originHeight=960\&originWidth=1344\&originalType=binary\&ratio=1\&size=123320\&status=done\&style=none\&width=672)

### 网格

用来调整坐标上的网格：

```bash
# panel.grid # 全部网格
# panel.grid.major # 主网格
# panel.grid.minor # 副网格
```

```bash
ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") +
  labs(x = "Year", y = "Temperature (°F)") +
  theme(panel.grid.major = element_line(size = .5, linetype = "dashed"),
        panel.grid.minor = element_line(size = .25, linetype = "dotted"),
        panel.grid.major.x = element_line(color = "red1"),
        panel.grid.major.y = element_line(color = "blue1"),
        panel.grid.minor.x = element_line(color = "red4"),
        panel.grid.minor.y = element_line(color = "blue4"))
```

![](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618488621388-36a1f3c6-661c-4544-8bf5-a2b34661367f.png#height=480\&id=u01326bf5\&margin=%5Bobject%20Object%5D\&originHeight=960\&originWidth=1344\&originalType=binary\&ratio=1\&size=109670\&status=done\&style=none\&width=672) 当然，我们也可以赋值element\_blank() 移除网格。

我们也可以通过坐标轴处理函数scale\_y\_continuous 来限定网格的距离：

```bash
ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") +
  labs(x = "Year", y = "Temperature (°F)") +
  scale_y_continuous(breaks = seq(0, 100, 10),
                     minor_breaks = seq(0, 100, 2.5))
```

![](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618489061199-1ffb4f30-2de8-4f28-935b-2f7ffe5b8a47.png#height=480\&id=u876d2d9d\&margin=%5Bobject%20Object%5D\&originHeight=960\&originWidth=1344\&originalType=binary\&ratio=1\&size=125190\&status=done\&style=none\&width=672)

### 边界

基础包绘图时，我们可能会用到mai 或mar 来控制边界，同样的，ggplot 中也提供了参数： `plot.margin = margin`：

```bash
ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") +
  labs(x = "Year", y = "Temperature (°F)") +
  theme(plot.background = element_rect(fill = "gray60"),
        plot.margin = margin(t = 1, r = 3, b = 1, l = 8, unit = "cm"))
```

![](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618489913032-cb646ad2-85d5-4af0-9f2f-2b2be38cf935.png#height=480\&id=uea58f422\&margin=%5Bobject%20Object%5D\&originHeight=960\&originWidth=1344\&originalType=binary\&ratio=1\&size=97915\&status=done\&style=none\&width=672) 上下左右对应前文的trouble 规则。

### 调整分面的文字带

在ggplot 中，分面的这部分内容，被称为strip： ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618806213887-d20c0311-3f9a-4410-9a3f-b91d3a014f26.png#height=121\&id=u09a75fab\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=241\&originWidth=614\&originalType=binary\&ratio=1\&size=35579\&status=done\&style=none\&width=307)

比如：

```
ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "orangered", alpha = .3) +
  labs(x = "Year", y = "Temperature (°F)") +
  facet_grid(season ~ year) + 
  theme(strip.text = element_text(face = "bold", color = "chartreuse4",
                                  hjust = 0, size = 20),
        strip.background = element_rect(fill = "chartreuse3", linetype = "dotted"))
```

![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618806341996-6eb2e75d-998b-4596-8982-b9a01747b53e.png#height=339\&id=u63886af7\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=678\&originWidth=1280\&originalType=binary\&ratio=1\&size=98015\&status=done\&style=none\&width=640)

作者这里还提供了两套函数，借助ggtext 包，对strip 文本进行美化：

```
library(ggtext)
library(rlang)
# 美化文本
element_textbox_highlight <- function(..., hi.labels = NULL, hi.fill = NULL,
                                      hi.col = NULL, hi.box.col = NULL, hi.family = NULL) {
  structure(
    c(element_textbox(...),
      list(hi.labels = hi.labels, hi.fill = hi.fill, hi.col = hi.col, hi.box.col = hi.box.col, hi.family = hi.family)
    ),
    class = c("element_textbox_highlight", "element_textbox", "element_text", "element")
  )
}

# 高亮分面
element_grob.element_textbox_highlight <- function(element, label = "", ...) {
  if (label %in% element$hi.labels) {
    element$fill <- element$hi.fill %||% element$fill
    element$colour <- element$hi.col %||% element$colour
    element$box.colour <- element$hi.box.col %||% element$box.colour
    element$family <- element$hi.family %||% element$family
  }
  NextMethod()
}

# 画图
g + facet_wrap(year ~ season, nrow = 4, scales = "free_x") +
  theme(
    strip.background = element_blank(),
    strip.text = element_textbox_highlight(
      family = "Playfair", size = 12, face = "bold",
      fill = "white", box.color = "chartreuse4", color = "chartreuse4",
      halign = .5, linetype = 1, r = unit(5, "pt"), width = unit(1, "npc"),
      padding = margin(5, 0, 3, 0), margin = margin(0, 1, 3, 1),
      hi.labels = c("1997", "1998", "1999", "2000"),
      hi.fill = "chartreuse4", hi.box.col = "black", hi.col = "white"
    )
  )
```

![](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618806593900-a6ba07af-dde5-4232-83cf-dd18ffc76c8c.png#height=768\&id=ufb98b365\&margin=%5Bobject%20Object%5D\&originHeight=1536\&originWidth=1344\&originalType=binary\&ratio=1\&status=done\&style=none\&width=672)

或者，还可以从分面的图像中高亮其中某块：

```
ggplot(chic, aes(x = date, y = temp)) +
  geom_point(aes(color = season == "Summer"), alpha = .3) +
  labs(x = "Year", y = "Temperature (°F)") +
  facet_wrap(~ season, nrow = 1) +
  scale_color_manual(values = c("gray40", "firebrick"), guide = "none") +
  theme(
    axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1),
    strip.background = element_blank(),
    strip.text = element_textbox_highlight(
      size = 12, face = "bold",
      fill = "white", box.color = "white", color = "gray40",
      halign = .5, linetype = 1, r = unit(0, "pt"), width = unit(1, "npc"),
      padding = margin(2, 0, 1, 0), margin = margin(0, 1, 3, 1),
      hi.labels = "Summer", hi.family = "Bangers",
      hi.fill = "firebrick", hi.box.col = "firebrick", hi.col = "white"
    )
  )
```

![](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618807184354-b6461013-52fe-4fc6-a67a-0c6adb0bb7c6.png#height=336\&id=u194cd102\&margin=%5Bobject%20Object%5D\&originHeight=672\&originWidth=1344\&originalType=binary\&ratio=1\&status=done\&style=none\&width=672) 相当好看了。

### 自带主题

ggplot2 提供了多种自带的主题，我们可以直接使用它们：

```bash
theme_gray() 默认主题，灰色。
theme_bw() 非常适合显示透明度的映射内容。
theme_void() 去除非数据外的全部内容。
theme_classic() # 经典ggplot 主题，白板背景。
```

![](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618823350483-fbe82baa-5db6-4c5b-9eed-9a6b096a44dc.png#height=672\&id=uce17d344\&margin=%5Bobject%20Object%5D\&originHeight=1344\&originWidth=2112\&originalType=binary\&ratio=1\&status=done\&style=none\&width=1056)

有个专门的R 包ggtheme 提供了各种杂志

需要注意的是，当我们使用了自带主题之后，先前的所有theme 设定都会被覆盖，因此如果想在默认主题下进行额外的操作，需要在之后添加。

## 7. ggplot 中的独立对象

### title

这里的title 指的是图片左上方的整个图片的标题： ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1617548815643-92dba6e1-358b-470c-9a90-6f7e3c6f1554.png#height=515\&id=OLyHK\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1030\&originWidth=1582\&originalType=binary\&ratio=1\&size=232449\&status=done\&style=none\&width=791) 直接通过`ggtitle` 创建。

### labs

包含了ggplot 图形中的各种文本类型对象：

```
ggplot(chic, aes(x = date, y = temp)) +
  geom_point(color = "firebrick") +
  labs(x = "Year", y = "Temperature (°F)",
       title = "Temperatures in Chicago",
       subtitle = "Seasonal pattern of daily temperatures from 1997 to 2001",
       caption = "Data: NMMAPS",
       tag = "Fig. 1")
```

![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1617584641382-ea19890f-3044-4ee3-b513-cca24f825b85.png#height=517\&id=wDk5b\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1034\&originWidth=1500\&originalType=binary\&ratio=1\&size=240362\&status=done\&style=none\&width=750)

如果是修改图例的标题，可以使用图例对应的aes 属性修改，比如创建的是在aes 中定义了color，则可以在labs 中指定：

```r
ggplot(chic, aes(x = date, y = temp, color = season)) +
  geom_point() +
  labs(x = "Year", y = "Temperature (°F)",
       color = "Seasons\nindicated\nby colors:")
```

## 8. 拼图

我目前还是主要使用aplot 与patchwork。

### cowplot/gridExtra

个人认为，其语法上没有patchwork 简洁：

* cowplot

![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618809045833-53e3f239-b956-4a98-8418-ebd5e6724f71.png#height=374\&id=ufdb3bf1f\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=628\&originWidth=775\&originalType=binary\&ratio=1\&size=219160\&status=done\&style=none\&width=461.5)

* gridExtra

![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1618809062714-e3b873e9-c44f-43cb-b0cb-328be8b3e35a.png#height=444\&id=u8bff1265\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=685\&originWidth=852\&originalType=binary\&ratio=1\&size=226766\&status=done\&style=none\&width=552)

## 易错点

1. 对于color, shape 等不连续的变量区分参数，不适于映射连续变量。（其一无法体现连续变量的变化趋势，其二这些不连续的参数其数量有限，无法有效区分连续变量）对于连续变量可以选择size, alpha等。
