# 03 ggplot2三部曲之基础二

* Date : 2021-11-25\_Thu
* 微信公众号 : 北野茶缸子
* Tags : #R/R可视化 #R/R数据科学 #R/index/01
* 参考：

## 开始前

![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597137362732-3ad66d41-589a-4ade-b44c-0d1a8a854a35.png#height=577\&id=QKzFj\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1154\&originWidth=2116\&originalType=binary\&ratio=1\&size=577698\&status=done\&style=none\&width=1058) 主要为ggplot2 中的后四个部分的内容。

## geometries 几何对象

### 不同的几何对象

![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597139417565-ad0f0045-813d-4a8d-bddd-1ea453c256fc.png#height=621\&id=BbJCE\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1242\&originWidth=2556\&originalType=binary\&ratio=1\&size=1014799\&status=done\&style=none\&width=1278)

### 几何对象的叠加

几何对象的本质，也就是画面上的不同图层。当我们通过 `ggplot(data=example)` 后，便相当于设定了默认的ggplot2 设定的背景图层，接着依靠 `+geom_point()` , `+geom_bar()` 等等，便可以实现图层的添加。

也正因其代表不同的图层，因此也可以利用新的图层对旧的图层进行叠加（或覆盖）。 ![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597139685128-1667d20d-6bf6-4c7c-ba05-0b4ddfad69d5.png#height=573\&id=Yxb5F\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1146\&originWidth=2400\&originalType=binary\&ratio=1\&size=814511\&status=done\&style=none\&width=1200)

#### 先后顺序

但也正和图层的叠加一样，R中ggplot 的叠加也有先后顺序，后来的图层会覆盖在原来的图层上。

```r
library(ggplot2)

test = iris

ggplot(data=test,aes(x=Species,y=Sepal.Width))+
  geom_point()+
  geom_boxplot(aes(color=Species))
```

![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597140238512-cfa7c4b5-ecf6-430c-b818-48f75139f3a1.png#height=371\&id=bnEbY\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=742\&originWidth=1200\&originalType=binary\&ratio=1\&size=70999\&status=done\&style=none\&width=600)

```r
library(ggplot2)

test = iris

ggplot(data=test,aes(x=Species,y=Sepal.Width))+
  geom_boxplot(aes(color=Species))+
  geom_point()
```

![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597140260311-1c272874-5acd-4ba6-8563-74cbc9991d65.png#height=374\&id=Fi0qL\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=748\&originWidth=1194\&originalType=binary\&ratio=1\&size=73361\&status=done\&style=none\&width=597)

### 全局与局部映射

我们可以设定整个图像中图层的参数，依靠设置 `ggplot` ，也可以对不同的图层进行局部设定 `geom_xxx()` ，这样也就实现了局部和全局的映射设置。 ![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597139822215-c38afd55-5299-4a9b-8b8f-e7a0d3577cbe.png#height=640\&id=JMb2J\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1280\&originWidth=2546\&originalType=binary\&ratio=1\&size=1357382\&status=done\&style=none\&width=1273)

#### 映射冲突

如果全局映射与局部映射发生冲突，则以局部映射为准。

```r
library(ggplot2)

test = iris

ggplot(data=test,aes(x=Species,y=Sepal.Width,color=Species))+
  geom_boxplot()+
  geom_point(color='black')
```

![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597140948195-8eaffd5f-4d11-4268-877e-b37fc9db9ace.png#height=373\&id=rG5zY\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=746\&originWidth=1170\&originalType=binary\&ratio=1\&size=72537\&status=done\&style=none\&width=585)

## statistics 统计变换

### 对应几何图形

几何图形函数一般都会对应一个统计变换函数的图形。 ![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597152474650-7d917c1a-d0d5-4426-9dc4-956a6e0be9c9.png#height=495\&id=DKmWv\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=990\&originWidth=2454\&originalType=binary\&ratio=1\&size=513937\&status=done\&style=none\&width=1227) 因此某种程度来说，统计变换对应的函数和几何对象对应的函数差别不大。

`geom_bar` 相当于默认的帮助我们以cut 列作为统计对象，对diamonds 表格进行频数计算。 对此我们可以使用 `table` 并转换为 `dataframe` 自行实现。

```r
freq = as.data.frame(table(diamonds$cut))
freq
       Var1  Freq
1      Fair  1610
2      Good  4906
3 Very Good 12082
4   Premium 13791
5     Ideal 21551

ggplot(data = freq) +
  geom_bar(mapping = aes(x = Var1, y = Freq), stat = "identity")
```

### 相关参数

#### stat

当需要对直方图自定义x,y 时，需要设定参数 `stat` ，其默认参数为 `count` （也正因此geom\_bar 对应stat\_count），它会计算出选择的对象在出现的频数作为y。因此若我们希望自定义y，需要将其改为 `identity` 。否则会报错。

```r
> ggplot(data = fre) +
+   geom_bar(mapping = aes(x = Var1, y = Freq))
Error: stat_count() can only have an x or y aesthetic.
Run `rlang::last_error()` to see where the error occurred.
```

#### ..prop..

若希望显示出的不是频数，而是频率，则可以通过为y 赋值，将直方图计算出的统计结果重新映射给比例 `..prop..` 。

```r
ggplot(data = diamonds) + 
  geom_bar(mapping = aes(x = cut, y = ..prop.., group = 1))
```

## position 位置调整

一般的位置调整问题存在于散点图或直方图中，指的是变量经过ggplot 转换而成的图形所进行的位置调整。

### 散点图

#### jitter

通过为本来重叠在同一位置的点添加随机的“抖动”，使重叠的点产生错位，也因此能够完全地显示在图像里。 ![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597155798187-c9a0946a-66fd-4c6b-8577-b3826f94f8c7.png#height=374\&id=zHFMv\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1276\&originWidth=2548\&originalType=binary\&ratio=1\&size=490814\&status=done\&style=none\&width=746)

### 柱状图

#### dodge

可以让组中的直方图并列显示。（适合组间或组内参数的比较）

```r
ggplot(data = diamonds) + 
  geom_bar(mapping = aes(x = cut, fill = clarity), position = "dodge")
```

![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597156544237-3d87668d-4fd5-4584-bdfa-5e15793ea05d.png#height=370\&id=HLhVe\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=740\&originWidth=1168\&originalType=binary\&ratio=1\&size=69900\&status=done\&style=none\&width=584)

#### stack

默认的直方图其位置参数即为 `stack` 。图形堆叠在一起。（适合整体的比较）

```r
ggplot(data = diamonds) + 
  geom_bar(mapping = aes(x = cut,fill=clarity))
```

![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597156402549-b9e1260b-87b0-495b-9904-eaf9361a0d29.png#height=368\&id=XPQlh\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=736\&originWidth=1168\&originalType=binary\&ratio=1\&size=66941\&status=done\&style=none\&width=584)

#### fill

与 `stack` 类似，只不过显示的是各部分占其整体的比重。（无法比较各组之间大小差异）

```r
ggplot(data = diamonds, aes(cut, fill = clarity)) +
  geom_bar(position = 'fill')
```

![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597156694550-3da068bc-d972-4a97-a750-5d8c094ee276.png#height=368\&id=ycvjo\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=736\&originWidth=1108\&originalType=binary\&ratio=1\&size=69412\&status=done\&style=none\&width=554)

## coordinate 坐标系

### 翻转坐标系

```r
ggplot(data = mpg, mapping = aes(x = class, y = hwy)) + 
  geom_boxplot() +
  coord_flip()
```

### 极坐标系

```r
bar <- ggplot(data = diamonds) + 
  geom_bar(
    mapping = aes(x = cut, fill = cut), 
    show.legend = FALSE,
    width = 1
  ) + 
  theme(aspect.ratio = 1) +
  labs(x = NULL, y = NULL)
bar + coord_flip()
bar + coord_polar()
```

![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597157196659-41f1ff01-699a-42ea-acd1-6b275afda166.png#height=365\&id=ePCI4\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=730\&originWidth=916\&originalType=binary\&ratio=1\&size=74953\&status=done\&style=none\&width=458)

## theme 主题

通过theme 可以改变绘图图形本来的一些样式，属于非常细节的部分。通常来说，theme 可以定义一些非数据的绘图元素，包括：

```r
Axis label aesthetics
Plot background
Facet label backround
Legend appearance
```

我们可以使用ggplot 内建的theme。

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

```r
ggplot(data = mpg, mapping = aes(x = class, y = hwy)) + 
  geom_boxplot() +
  theme_void()
```

![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597157713494-0ca2ce7f-d550-451a-bfd5-6ac72233185e.png#height=380\&id=NJL8n\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=760\&originWidth=1194\&originalType=binary\&ratio=1\&size=32387\&status=done\&style=none\&width=597) 我们还可以直接定义theme 中的参数，如通过`rel`函数将字体大小提升到1.5倍：

```r
ggplot(new_metadata) +
  geom_point(aes(x = age_in_days, y= samplemeans, color = genotype,
  			shape=celltype), size=3.0) +
  theme_bw() +
  theme(axis.title = element_text(size=rel(1.5)))	
```

### labs

labs 可以对ggplot2 绘图中的标签进行修改。

```r
library(ggplot2)
p <- ggplot(mtcars, aes(mpg, wt, colour = cyl)) + geom_point()
p + labs(colour = "Cylinders") # 图例标签修改
p + labs(x = "New x label") # x轴标签
p + labs(title = "New plot title", subtitle = "A subtitle", tag="A") # 标题与子标题，以及右上方子图标记
p + labs(caption = "(based on data from ...)") # 右下方的说明标签
p + labs(title = NULL) # 移除先前的标签，直接赋值为NULL 即可。
```

在使用labs 属性定义图像时，还可以使用`expression` 语句，生成绘图中的希腊字母、特殊符号或公式，但该包的语法比较奇怪，比如：

```r
expression(paste("Temperature (", degree ~ F, ")"^"(Hey, why should we use metric units?!)")))
```

![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1617456574610-10b63e28-89e4-4339-8fa4-808939f706e2.png#height=109\&id=sNS1O\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=218\&originWidth=948\&originalType=binary\&ratio=1\&size=31413\&status=done\&style=none\&width=474)

```r
expression(paste(bold("log"["2"])*italic(sigma)," + ",bold("log"["2"])*bolditalic(alpha)))
```

![image.png](https://cdn.nlark.com/yuque/0/2021/png/1153133/1617456508675-09fb6a50-ea16-4042-ab8a-e7a45324b24e.png#height=37\&id=IPADl\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=74\&originWidth=356\&originalType=binary\&ratio=1\&size=4384\&status=done\&style=none\&width=178)

### 自定义主题

如果我们想保留某类主题作为模版，这样就不用在绘制新图时反复调用它了：

```r
personal_theme <- function(){
  theme_bw() +
    theme(axis.title=element_text(size=rel(1.5)),
          plot.title=element_text(size=rel(1.5), hjust=0.5)) 
}
```

另外，如果希望主题在全局生效，可以直接使用函数：

```r
theme_set(theme_bw())
```

## 完整绘图模版

![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597157270773-26930712-0bcb-4d12-80aa-bcbf40f2ee63.png#height=533\&id=sNQzZ\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=1066\&originWidth=1120\&originalType=binary\&ratio=1\&size=182838\&status=done\&style=none\&width=560)

## 易错点

1. 局部映射与全局映射冲突时，以局部映射为准。
2. 图层存在先后顺序，后来的图层越靠近顶层。
3. ggplot2 无法借助循环直接批量将绘图映射在同一层面上，可以借助列表先存储这些绘图，再使用拼图函数将它们拼接在同一画面上。

## 练习题

### 6-2

```r
#练习6-2
# 1.尝试写出下图的代码
# 数据是iris
# X轴是Species
# y轴是Sepal.Width
# 图是箱线图
library(ggplot2)

test = iris

ggplot(data=test,aes(x=Species,y=Sepal.Width))+
  geom_boxplot(aes(color=Species))+
  geom_point()

# 2. 尝试在此图上叠加点图，
# 能发现什么问题？
点图覆盖在箱线图上。后设定的图层在更靠近顶层的位置。

# 3.用下列代码作图，观察结果
ggplot(test,aes(x = Sepal.Length,y = Petal.Length,color = Species)) +
  geom_point()+
  geom_smooth(color = "black")
 
# 请问，当局部映射和全局映射冲突，以谁为准？
局部为准
```

### 6-3

```r
if(!require(ggplot))install.packages("ggplot")
library(ggplot2)

test <- iris
ggplot(data=test,
       aes(x=Sepal.Width, y=Species)) +
  geom_violin(aes(fill=Species)) +
  geom_boxplot(aes(group=Species)) +
  geom_jitter(aes(shape=Species)) +
  theme_bw()
```

![image.png](https://cdn.nlark.com/yuque/0/2020/png/1153133/1597158409957-12bdb148-98fd-4fd4-98bf-ffa1cb317b3b.png#height=378\&id=TADfI\&margin=%5Bobject%20Object%5D\&name=image.png\&originHeight=756\&originWidth=1154\&originalType=binary\&ratio=1\&size=116349\&status=done\&style=none\&width=577)


---

# 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/03-ggplot2-san-bu-qu-zhi-ji-chu-er.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.
