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

# 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)
