# 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等。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET 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?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
