-
Notifications
You must be signed in to change notification settings - Fork 25
/
graphics-foundations.Rmd
1919 lines (1574 loc) · 52.3 KB
/
graphics-foundations.Rmd
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# 图形基础 {#chap-graphics-foundations}
```{r}
library(survival)
library(lattice)
library(nlme)
library(MASS)
library(RColorBrewer)
library(latticeExtra)
library(shape)
library(splines)
library(mgcv)
library(maps)
library(mapproj)
```
<!--
作为知识介绍,本章所有数据都来源于基础 R 包,即安装 R 软件后自带的数据集,图库在以 base R 中的数据集介绍完后,以相应真实数据扩展为案列,结合统计意义和探索性数据分析介绍各种常见统计图形
-->
数据可视化是一种重要的数据分析手段, R 提供了两套图形系统,分别是 graphics 包提供的基础绘图系统和 grid 包提供的栅格绘图系统,后者主要以两个 R 包为大家所熟知,一个是 lattice 包,另一个是 ggplot2 包。
Base 图形系统的扩展包 [basetheme](https://github.com/KKPMW/basetheme) 可以设置主题,[prettyB](https://github.com/jumpingrivers/prettyB) 和 [gridGraphics](https://github.com/pmur002/gridgraphics)
为了方便记忆函数 `par` 的各个参数,Paul Murrell 整理了一份 [助记符](https://www.stat.auckland.ac.nz/~paul/R/parMemnonics.html),此外,LaTeX 宏包 [geometry](https://github.com/latexstudio/LaTeXPackages-CN) 对版面设置有很多专业的说明
## 绘图基本要素 {#graphics-elements}
### 点线 {#base-points}
点和线是最常见的画图元素,在 `plot` 函数中,分别用参数 `pch` 和 `lty` 来设定类型,点的大小、线的宽度分别用参数 `cex` 和 `lwd` 来指定,颜色由参数 `col` 设置。参数 `type` 不同的值设置如下,`p` 显示点,`l` 绘制线,`b` 同时绘制空心点,并用线连接,`c` 只有线,`o` 在线上绘制点,`s` 和 `S` 点线连接绘制阶梯图,`h` 绘制类似直方图一样的垂线,最后 `n` 表示什么也不画。
点 points 、线 grid 背景线 abline lines rug 刻度线(线段segments、箭头arrows)、
```{r, fig.cap="不同的 pch 参数值", fig.width=4, fig.height=4, out.width="75%"}
## -------- Showing all the extra & some char graphics symbols ---------
pchShow <-
function(extras = c("*", ".", "o", "O", "0", "+", "-", "|", "%", "#"),
cex = 2, ## good for both .Device=="postscript" and "x11"
col = "red3", bg = "gold", coltext = "brown", cextext = 1.2,
main = paste(
"plot symbols : points (... pch = *, cex =",
cex, ")"
)) {
nex <- length(extras)
np <- 26 + nex
ipch <- 0:(np - 1)
k <- floor(sqrt(np))
dd <- c(-1, 1) / 2
rx <- dd + range(ix <- ipch %/% k)
ry <- dd + range(iy <- 3 + (k - 1) - ipch %% k)
pch <- as.list(ipch) # list with integers & strings
if (nex > 0) pch[26 + 1:nex] <- as.list(extras)
plot(rx, ry, type = "n", axes = FALSE, xlab = "", ylab = "", main = main)
abline(v = ix, h = iy, col = "lightgray", lty = "dotted")
for (i in 1:np) {
pc <- pch[[i]]
## 'col' symbols with a 'bg'-colored interior (where available) :
points(ix[i], iy[i], pch = pc, col = col, bg = bg, cex = cex)
if (cextext > 0) {
text(ix[i] - 0.3, iy[i], pc, col = coltext, cex = cextext)
}
}
}
pchShow()
```
```{r,fig.cap="pch 支持的字符",out.width="45%",fig.width=4.5,fig.asp=1}
## ------------ test code for various pch specifications -------------
# Try this in various font families (including Hershey)
# and locales. Use sign = -1 asserts we want Latin-1.
# Standard cases in a MBCS locale will not plot the top half.
TestChars <- function(sign = 1, font = 1, ...) {
MB <- l10n_info()$MBCS
r <- if (font == 5) {
sign <- 1
c(32:126, 160:254)
} else if (MB) 32:126 else 32:255
if (sign == -1) r <- c(32:126, 160:255)
par(pty = "s")
plot(c(-1, 16), c(-1, 16),
type = "n", xlab = "", ylab = "",
xaxs = "i", yaxs = "i",
main = sprintf("sign = %d, font = %d", sign, font)
)
grid(17, 17, lty = 1)
mtext(paste("MBCS:", MB))
for (i in r) try(points(i %% 16, i %/% 16, pch = sign * i, font = font, ...))
}
TestChars()
try(TestChars(sign = -1))
TestChars(font = 5) # Euro might be at 160 (0+10*16).
# macOS has apple at 240 (0+15*16).
try(TestChars(-1, font = 2)) # bold
```
```{r,fig.cap="不同的 type 参数值",fig.asp=1}
x <- 0:12
y <- sin(pi / 5 * x)
par(mfrow = c(3, 3), mar = .1 + c(2, 2, 3, 1))
for (tp in c("p", "l", "b", "c", "o", "h", "s", "S", "n")) {
plot(y ~ x, type = tp, main = paste0("plot(*, type = \"", tp, "\")"))
if (tp == "S") {
lines(x, y, type = "s", col = "red", lty = 2)
mtext("lines(*, type = \"s\", ...)", col = "red", cex = 0.8)
}
}
```
颜色 col 连续型和离散型
线帽/端和字体的样式
```{r,fig.asp=1,out.width="55%",fig.width=4.71,fig.cap="不同的线端样式"}
# 合并为一个图 三条粗横线 横线上三种字形
plot(c(1, 20), c(1, 20), type = "n", ann = FALSE)
lines(x = c(5, 15), y = c(5, 5), lwd = 15, lend = "round")
text(10, 5, "Hello, Helvetica", cex = 1.5, family = "sans", pos = 1, offset = 1.5)
text(5, 5, "sans", cex = 1.5, family = "sans", pos = 2, offset = .5)
text(15, 5, "lend = round", pos = 4, offset = .5)
lines(x = c(5, 15), y = c(10, 10), lwd = 15, lend = "butt")
text(10, 10, "Hello, Helvetica", cex = 1.5, family = "mono", pos = 1, offset = 1.5)
text(5, 10, "mono", cex = 1.5, family = "mono", pos = 2, offset = .5)
text(15, 10, "lend = butt", pos = 4, offset = .5)
lines(x = c(5, 15), y = c(15, 15), lwd = 15, lend = "square")
text(10, 15, "Hello, Helvetica", cex = 1.5, family = "serif", pos = 1, offset = 1.5)
text(5, 15, "serif", cex = 1.5, family = "serif", pos = 2, offset = .5)
text(15, 15, "lend = square", pos = 4, offset = .5)
```
lend:线端的样式,可用一个整数或字符串指定:
- 0 或 "round" 圆形(默认)
- 1 或 "butt" 对接形
- 2 或 "square" 方形
### 区域 {#base-rect}
矩形,多边形,曲线交汇出来的区域
面(矩形rect,多边形polygon)、路径 polypath
面/多边形 rect 颜色填充
```{r,fig.cap="rect 函数画长方形",fig.asp=1}
# From the manual
ch.col <- c(
"rainbow(n, start=.7, end=.1)",
"heat.colors(n)",
"terrain.colors(n)",
"topo.colors(n)",
"cm.colors(n)"
) # 选择颜色
n <- 16
nt <- length(ch.col)
i <- 1:n
j <- n / nt
d <- j / 6
dy <- 2 * d
plot(i, i + d,
type = "n",
yaxt = "n",
ylab = "",
xlab = "",
main = paste("color palettes; n=", n)
)
for (k in 1:nt) {
rect(i - .5, (k - 1) * j + dy, i + .4, k * j,
col = eval(parse(text = ch.col[k]))
) # 咬人的函数/字符串解析为/转函数
text(2 * j, k * j + dy / 4, ch.col[k])
}
```
`clip(x1, x2, y1, y2)` 在用户坐标中设置剪切区域
```{r,title.mar=TRUE}
x <- rnorm(1000)
hist(x, xlim = c(-4, 4))
usr <- par("usr")
clip(usr[1], -2, usr[3], usr[4])
hist(x, col = "red", add = TRUE)
clip(2, usr[2], usr[3], usr[4])
hist(x, col = "blue", add = TRUE)
do.call("clip", as.list(usr)) # reset to plot region
```
```{r,fig.cap="区域重叠 polygon 函数",fig.asp=1,fig.width=5.5,out.width="55%"}
my.col <- function(f, g, xmin, xmax, col, N = 200,
xlab = "", ylab = "", main = "") {
x <- seq(xmin, xmax, length = N)
fx <- f(x)
gx <- g(x)
plot(0, 0,
type = "n",
xlim = c(xmin, xmax),
ylim = c(min(fx, gx), max(fx, gx)),
xlab = xlab, ylab = ylab, main = main
)
polygon(c(x, rev(x)), c(fx, rev(gx)),
col = "#EA4335", border = 0
)
lines(x, fx, lwd = 3, col = "#34A853")
lines(x, gx, lwd = 3, col = "#4285f4")
}
my.col(function(x) x^2, function(x) x^2 + 10 * sin(x),
-6, 6,
main = "The \"polygon\" function"
)
```
各种符号 \@ref(fig:cex-symbol)
```{r cex-symbol,fig.cap="cex 支持的符号",fig.asp=1,fig.width=5.5,out.width="55%"}
plot(0, 0,
xlim = c(1, 5), ylim = c(-.5, 4),
axes = F,
xlab = "", ylab = ""
)
for (i in 0:4) {
for (j in 1:5) {
n <- 5 * i + j
points(j, i,
pch = n,
cex = 3
)
text(j, i - .3, as.character(n))
}
}
```
点、线、多边形和圆聚集在图 \@ref(fig:symbols) 中
```{r symbols,fig.cap="多边形和符号元素"}
# https://jeroen.github.io/uros2018/#23
plot.new()
plot.window(xlim = c(0, 100), ylim = c(0, 100))
polygon(c(10, 40, 80), c(10, 80, 40), col = "hotpink")
text(40, 90, labels = "My drawing", col = "navyblue", cex = 3)
symbols(c(70, 80, 90), c(20, 50, 80),
circles = c(10, 20, 10),
bg = c("#4285f4", "#EA4335", "red"), add = TRUE, lty = "dashed"
)
```
在介绍各种统计图形之前,先介绍几个绘图函数 `plot` 和 `text` 还有 `par` 参数设置, 作为最简单的开始,尽量依次介绍其中的每个参数的含义并附上图形对比。
```{r pos,fig.cap="pos 位置参数",out.width="55%",fig.asp=1,fig.width=5.5,title.mar=TRUE}
y <- x <- 1:4
plot(x, y, ann = F, col = "blue", pch = 16)
text(x, y,
labels = c("1st", "2nd", "3rd", "4th"),
col = "red", pos = c(3, 4, 4, 1), offset = 0.6
)
ahat <- "sigma"
# title(substitute(hat(a) == ahat, list(ahat = ahat)))
title(bquote(hat(a) == .(ahat)))
```
其中 labels, pos 都是向量化的参数
### 参考线 {#base-lines}
矩形网格线是用做背景参考线的,常常是淡灰色的细密虚线,`plot` 函数的 `panel.first` 参数和 `grid` 函数常用来画这种参考线
```{r bg-grid-lines,fig.cap="添加背景参考线",fig.asp=.8,fig.width=5}
# modified from https://yihui.name/cn/2018/02/cohen-s-d/
n <- 30 # 样本量(只是一个例子)
x <- seq(0, 12, 0.01)
par(mar = c(4, 4, 0.2, 0.1))
plot(x / sqrt(n), 2 * (1 - pt(x, n - 1)),
xlab = expression(d = x / sqrt(n)),
type = "l", panel.first = grid()
)
abline(v = c(0.01, 0.2, 0.5, 0.8, 1.2, 2), lty = 2)
```
### 坐标轴 {#base-axis}
图形控制参数默认设置下 `par` 通常的一幅图形,改变坐标轴标签是很简单的
```{r}
x <- 1:100
y <- runif(100, -2, 2)
plot(x, y)
plot(x, y, xlab = "Index", ylab = "Uniform draws")
```
改变坐标轴标签和标题
```{r}
op <- par(no.readonly = TRUE) # 保存默认的 par 设置
par(cex.lab = 1.5, cex.axis = 1.3)
plot(x, y, xlab = "Index", ylab = "Uniform draws")
# 设置更大的坐标轴标签内容
par(mar = c(6, 6, 3, 3), cex.axis = 1.5, cex.lab = 2)
plot(x, y, xlab = "Index", ylab = "Uniform draws")
```
使用 axis 函数可以更加精细地控制坐标轴
```{r}
par(op) # 恢复默认的 par 设置
plot(x, y, xaxt = "n") # 去掉 x 轴
axis(side = 1, at = c(5, 50, 100)) # 添加指定的刻度标签
```
指定刻度标签的内容
```{r}
plot(x, y, yaxt = "n")
axis(side = 2, at = c(-2, 0, 2), labels = c("Small", "Medium", "Big"))
```
控制刻度线和轴线和刻度标签
```{r}
plot(x, y)
axis(side = 3, at = c(5, 25, 75), lwd = 4, lwd.ticks = 2, col.ticks = "red")
```
还可以把 box 移除,绘图区域的边框去掉,只保留坐标轴
```{r}
plot(x, y, bty = "n", xaxt = "n", yaxt = "n")
axis(side = 1, at = seq(0, 100, 20), lwd = 3)
axis(side = 2, at = seq(-2, 2, 2), lwd = 3)
```
```{r,fig.cap="两个 Y 轴",fig.asp=1,fig.width=6.5,out.width="65%"}
# 双Y轴
N <- 200
x <- seq(-4, 4, length = N)
y1 <- sin(x)
y2 <- cos(x)
op <- par(mar = c(5, 4, 4, 4)) # Add some space in the right margin
# The default is c(5,4,4,2) + .1
xlim <- range(x)
ylim <- c(-1.1, 1.1)
plot(x, y1,
col = "blue", type = "l",
xlim = xlim, ylim = ylim,
axes = F, xlab = "", ylab = "", main = "Title"
)
axis(1)
axis(2, col = "blue")
par(new = TRUE)
plot(x, y2,
col = "red", type = "l",
xlim = xlim, ylim = ylim,
axes = F, xlab = "", ylab = "", main = ""
)
axis(4, col = "red")
mtext("First Y axis", 2, line = 2, col = "blue", cex = 1.2)
mtext("Second Y axis", 4, line = 2, col = "red", cex = 1.2)
# 1,2,3,4 分别代表下左上右四个位置
```
调整坐标轴标签的距离
```{r gap-axis,fig.asp=1,fig.cap="gap.axis用法",fig.width=5.5,out.width="55%"}
## Changing default gap between labels:
plot(c(0, 100), c(0, 50), type = "n", axes = FALSE, ann = FALSE)
title(quote("axis(1, .., gap.axis = f)," ~ ~ f >= 0))
axis(2, at = 5 * (0:10), las = 1, gap.axis = 1 / 4)
gaps <- c(4, 2, 1, 1 / 2, 1 / 4, 0.1, 0)
chG <- paste0(
ifelse(gaps == 1, "default: ", ""),
"gap.axis=", formatC(gaps)
)
jj <- seq_along(gaps)
linG <- -2.5 * (jj - 1)
for (j in jj) {
isD <- gaps[j] == 1 # is default
axis(1,
at = 5 * (0:20), gap.axis = gaps[j], padj = -1, line = linG[j],
col.axis = if (isD) "forest green" else 1, font.axis = 1 + isD
)
}
mtext(chG,
side = 1, padj = -1, line = linG - 1 / 2, cex = 3 / 4,
col = ifelse(gaps == 1, "forest green", "blue3")
)
## now shrink the window (in x- and y-direction) and observe the axis labels drawn
```
旋转坐标轴标签
```{r}
# Rotated axis labels in R plots
# https://menugget.blogspot.com/2014/08/rotated-axis-labels-in-r-plots.html
# Example data
tmin <- as.Date("2000-01-01")
tmax <- as.Date("2001-01-01")
tlab <- seq(tmin, tmax, by = "month")
lab <- format(tlab, format = "%Y-%b")
set.seed(111)
x <- seq(tmin, tmax, length.out = 100)
y <- cumsum(rnorm(100))
# Plot
# png("plot_w_rotated_axis_labels.png", height = 3,
# width = 6, units = "in", res = 300)
op <- par(mar = c(6, 4, 1, 1))
plot(x, y, t = "l", xaxt = "n", xlab = "")
axis(1, at = tlab, labels = FALSE)
text(
x = tlab, y = par()$usr[3] - 0.1 * (par()$usr[4] - par()$usr[3]),
labels = lab, srt = 45, adj = 1, xpd = TRUE
)
par(op)
# dev.off()
```
旋转坐标抽标签的例子来自手册《R FAQ》的第7章第27个问题 [@R-FAQ],在基础图形中,旋转坐标轴标签需要 `text()` 而不是 `mtext()`,因为后者不支持`par("srt")`
```{r rotate-axis-labels,fig.cap="旋转坐标轴标签"}
## Increase bottom margin to make room for rotated labels
par(mar = c(5, 4, .5, 2) + 0.1)
## Create plot with no x axis and no x axis label
plot(1:8, xaxt = "n", xlab = "")
## Set up x axis with tick marks alone
axis(1, labels = FALSE)
## Create some text labels
labels <- paste("Label", 1:8, sep = " ")
## Plot x axis labels at default tick marks
text(1:8, par("usr")[3] - 0.5,
srt = 45, adj = 1,
labels = labels, xpd = TRUE
)
## Plot x axis label at line 6 (of 7)
mtext(side = 1, text = "X Axis Label", line = 4)
```
`srt = 45` 表示文本旋转角度, `xpd = TRUE` 允许文本越出绘图区域,`adj = 1` to place the right end of text at the tick marks;You can adjust the value of the 0.5 offset as required to move the axis labels up or down relative to the x axis. 详细地参考 [@Paul_2003_Integrating]
### 刻度线 {#base-tick}
通过 `par` 或 `axis` 函数实现刻度线的精细操作,tcl 控制刻度线的长度,正值让刻度画在绘图区域内,负值正好相反,画在外面,mgp 参数有三个值,第一个值控制绘图区域和坐标轴标题之间的行数,第二个是绘图区域与坐标轴标签的行数,第三个绘图区域与轴线的行数,行数表示间距
```{r}
par(tcl = 0.4, mgp = c(1.5, 0, 0))
plot(x, y)
# 又一个例子
par(op)
plot(x, y, xaxt = "n", yaxt = "n", xlab = "", ylab = "")
axis(side = 1, at = seq(5, 95, 30), tcl = 0.4, lwd.ticks = 3, mgp = c(0, 0.5, 0))
mtext(side = 1, text = "X axis", line = 1.5)
# mtext 设置坐标轴标签
axis(side = 2, at = seq(-2, 2, 2), tcl = 0.3, lwd.ticks = 3, col.ticks = "orange", mgp = c(0, 0, 2))
mtext(side = 2, text = "Numbers taken randomly", line = 2.2)
```
### 标题 {#base-title}
添加多个标题
```{r,fig.cap="图标题/子标题 x轴标题/子标题",sub.mar=TRUE}
N <- 200
x <- runif(N, -4, 4)
y <- sin(x) + .5 * rnorm(N)
plot(x, y, xlab = "", ylab = "", main = "")
mtext("Subtitle", 3, line = .8)
mtext("Title", 3, line = 2, cex = 1.5)
mtext("X axis", 1, line = 2.5, cex = 1.5)
mtext("X axis subtitle", 1, line = 3.7)
```
### 注释 {#base-annotation}
数学符号注释,图\@ref(fig:math-annotation) 自定义坐标轴 [@Paul_2000_Approach]。
```{r math-annotation, fig.cap="创建自定义的坐标轴和刻度标签",fig.asp=1,fig.width=4.5,out.width="45%"}
# 自定义坐标轴
plot(c(1, 1e6), c(-pi, pi),
type = "n",
axes = FALSE, ann = FALSE, log = "x"
)
axis(1,
at = c(1, 1e2, 1e4, 1e6),
labels = expression(1, 10^2, 10^4, 10^6)
)
axis(2,
at = c(-pi, -pi / 2, 0, pi / 2, pi),
labels = expression(-pi, -pi / 2, 0, pi / 2, pi)
)
text(1e3, 0, expression(italic("Customized Axes")))
box()
```
在标题中添加数学公式
```{r,fig.cap="标题含有数学公式",fig.asp=1,out.width="45%",fig.width=4.5}
x <- seq(-5, 5, length = 200)
y <- sqrt(1 + x^2)
plot(y ~ x,
type = "l",
ylab = expression(sqrt(1 + x^2))
)
title(main = expression(
"graph of the function f"(x) == sqrt(1 + x^2)
))
```
修改参数使用 `substitute` 函数批量生成
```{r,fig.cap="批量生成函数图形",fig.asp=1,out.width="45%",fig.width=4.5}
x <- seq(-5, 5, length = 200)
for (i in 1:4) { # 画四个图
y <- sqrt(i + x^2)
plot(y ~ x,
type = "l",
ylim = c(0, 6),
ylab = substitute(
expression(sqrt(i + x^2)),
list(i = i)
)
)
title(main = substitute(
"graph of the function f"(x) == sqrt(i + x^2),
list(i = i)
))
}
```
基础绘图函数,如 plot 标签 `xlab` 支持 Unicode 代码表示的希腊字母,常用字母表备查,公式环境下,也可以用在绘图中
Table: (\#tab:letters) 希腊字母表
希腊字母 | LaTeX 代码 | Unicode 代码 | 希腊字母 | LaTeX 代码 | Unicode 代码
:------------- | :------------- | :----------- | :---------- | :------------ | :-------------
$\alpha$ | `\alpha` | `\u03B1` | $\mu$ | `\mu` | `\u03BC`
$\beta$ | `\beta` | `\u03B2` | $\nu$ | `\nu` | `\u03BD`
$\gamma$ | `\gamma` | `\u03B3` | $\xi$ | `\xi` | `\u03BE`
$\delta$ | `\delta` | `\u03B4` | $\varphi$ | `\varphi` | `\u03C6`
$\epsilon$ | `\epsilon` | `\u03B5` | $\pi$ | `\pi` | `\u03C0`
$\zeta$ | `\zeta` | `\u03B6` | $\rho$ | `\rho` | `\u03C1`
$\eta$ | `\eta` | `\u03B7` | $\upsilon$ | `\upsilon` | `\u03C5`
$\theta$ | `\theta` | `\u03B8` | $\phi$ | `\phi` | `\u03C6`
$\iota$ | `\iota` | `\u03B9` | $\chi$ | `\chi` | `\u03C7`
$\kappa$ | `\kappa` | `\u03BA` | $\psi$ | `\psi` | `\u03C8`
$\lambda$ | `\lambda` | `\u03BB` | $\omega$ | `\omega` | `\u03C9`
$\sigma$ | `\sigma` | `\u03C3` | $\tau$ | `\tau` | `\u03C4`
Table: (\#tab:super-sub-script) 数字上下标
上标数字 | LaTeX 代码| Unicode 代码 | 下标数字 | LaTeX 代码 | Unicode 代码
:--------- |:--------- | :--------- | :--------- | :--------- | :---------
${}^0$ | `{}^0` | `\u2070` | ${}_0$ | `{}_0` | `\u2080`
${}^1$ | `{}^1` | `\u00B9` | ${}_1$ | `{}_1` | `\u2081`
${}^2$ | `{}^2` | `\u00B2` | ${}_2$ | `{}_2` | `\u2082`
${}^3$ | `{}^3` | `\u00B2` | ${}_3$ | `{}_3` | `\u2083`
${}^4$ | `{}^4` | `\u2074` | ${}_4$ | `{}_4` | `\u2084`
${}^5$ | `{}^5` | `\u2075` | ${}_5$ | `{}_5` | `\u2085`
${}^6$ | `{}^6` | `\u2076` | ${}_6$ | `{}_6` | `\u2086`
${}^7$ | `{}^7` | `\u2077` | ${}_7$ | `{}_7` | `\u2087`
${}^8$ | `{}^8` | `\u2078` | ${}_8$ | `{}_8` | `\u2088`
${}^9$ | `{}^9` | `\u2079` | ${}_9$ | `{}_9` | `\u2089`
${}^n$ | `{}^n` | `\u207F` | ${}_n$ | `{}_n` | -
其它字母,请查看 [Unicode 字母表][unicode-tab]
[unicode-tab]: https://www.ssec.wisc.edu/~tomw/java/unicode.html
### 图例 {#base-legend}
```{r,fig.cap="三角函数添加图例",fig.asp=0.8}
x <- seq(-6, 6, length = 200)
y <- sin(x)
z <- cos(x)
plot(y ~ x,
type = "l", lwd = 3,
ylab = "", xlab = "angle", main = "Trigonometric functions"
)
abline(h = 0, lty = 3)
abline(v = 0, lty = 3)
lines(z ~ x, type = "l", lwd = 3, col = "red")
legend(-6, -1,
yjust = 0,
c("Sine", "Cosine"),
lwd = 3, lty = 1, col = c(par("fg"), "red")
)
```
```{r,fig.cap="设置图例的位置",fig.asp=0.8}
xmin <- par("usr")[1]
xmax <- par("usr")[2]
ymin <- par("usr")[3]
ymax <- par("usr")[4]
plot(y ~ x,
type = "l", lwd = 3,
ylab = "", xlab = "angle", main = "Trigonometric functions"
)
abline(h = 0, lty = 3)
abline(v = 0, lty = 3)
lines(z ~ x, type = "l", lwd = 3, col = "red")
legend("bottomleft",
c("Sine", "Cosine"),
lwd = 3, lty = 1, col = c(par("fg"), "red")
)
```
```{r,fig.cap="insert 函数微调图例位置",fig.asp=0.8}
plot(y ~ x,
type = "l", lwd = 3,
ylab = "", xlab = "angle", main = "Trigonometric functions"
)
abline(h = 0, lty = 3)
abline(v = 0, lty = 3)
lines(z ~ x, type = "l", lwd = 3, col = "red")
legend("bottomleft",
c("Sine", "Cosine"),
inset = c(.03, .03),
lwd = 3, lty = 1, col = c(par("fg"), "red")
)
```
```{r,fig.cap="将图例放在绘图区域外面",fig.asp=0.8}
op <- par(no.readonly = TRUE)
plot(y ~ x,
type = "l", lwd = 3,
ylab = "", xlab = "angle", main = "Trigonometric functions"
)
abline(h = 0, lty = 3)
abline(v = 0, lty = 3)
lines(z ~ x, type = "l", lwd = 3, col = "red")
par(xpd = TRUE) # Do not clip to the drawing area 关键一行/允许出界
lambda <- .025
legend(par("usr")[1],
(1 + lambda) * par("usr")[4] - lambda * par("usr")[3],
c("Sine", "Cosine"),
xjust = 0, yjust = 0,
lwd = 3, lty = 1, col = c(par("fg"), "red")
)
par(op)
```
Hmisc 包的 labcurve 函数可以在曲线上放置名称,而不是遥远的图例上
### 边空 {#base-par}
边空分为内边空和外边空
```{r par-mai-oma,echo=FALSE,fig.cap="边空",fig.subcap=c("内边空","外边空"),out.width="35%",fig.align='center'}
knitr::include_graphics(path = paste(
system.file("help/figures", package = "graphics"),
c("mai.png", "oma.png"),
sep = "/"
))
```
`line` 第一行
```{r,fig.cap="外边空在图的边缘添加文字",title.mar=TRUE}
N <- 200
x <- runif(N, -4, 4)
y <- sin(x) + .5 * rnorm(N)
plot(x, y,
xlab = "", ylab = "",
main = paste(
"The \"mtext\" function",
paste(rep(" ", 60), collapse = "")
)
)
for (i in seq(from = 0, to = 1, by = 1)) {
mtext(paste("Line", i), 3, line = i)
}
```
`par`
```{r,sub.mar=TRUE,fig.asp=1,fig.cap="多图排列共享一个大标题"}
# 多图排列/分屏 page 47
# 最常用的是 par mfrow mfcol分别按行/列放置图形
op <- par(
mfrow = c(2, 2),
oma = c(0, 0, 4, 0) # Outer margins
)
for (i in 1:4) {
plot(runif(20), runif(20),
main = paste("random plot (", i, ")", sep = "")
)
}
par(op)
mtext("Four plots, without enough room for this title",
side = 3, font = 2, cex = 1.5, col = "red"
) # 总/大标题放不下
```
`par` 的 oma 用来设置外边空的大小,默认情形下没有外边空的
```{r}
par()$oma
```
我们可以自己设置外边空
```{r,fig.cap="设置外边空放置大标题",fig.asp=1,title.mar=TRUE}
op <- par(
mfrow = c(2, 2),
oma = c(0, 0, 3, 0) # Outer margins
)
for (i in 1:4) {
plot(runif(20), runif(20),
main = paste("random plot (", i, ")", sep = "")
)
}
par(op)
mtext("Four plots, with some room for this title",
side = 3, line = 1.5, font = 1, cex = 1.5, col = "red"
)
```
除了内边空还有外边空,内外边空用来放注释说明
```{r}
op <- par(no.readonly = TRUE)
par(oma = c(2, 2, 2, 2))
plot(1, 1, type = "n", xlab = "", ylab = "", xaxt = "n", yaxt = "n")
for (side in 1:4) {
inner <- round(par()$mar[side], 0) - 1
for (line in 0:inner) {
mtext(text = paste0("Inner line ", line), side = side, line = line)
}
outer <- round(par()$oma[side], 0) - 1
for (line in 0:inner) {
mtext(text = paste0("Outer line ", line), side = side, line = line, outer = TRUE)
}
}
```
外边空可以用来放图例
```{r}
set.seed(1234)
x <- runif(10)
y <- runif(10)
cols <- rep(hcl.colors(5), each = 2)
op <- par(oma = c(2, 2, 0, 4), mar = c(3, 3, 2, 0), mfrow = c(2, 2), pch = 16)
for (i in 1:4) {
plot(x, y, col = cols, ylab = "", xlab = "")
}
mtext(text = "A common x-axis label", side = 1, line = 0, outer = TRUE)
mtext(text = "A common y-axis label", side = 2, line = 0, outer = TRUE)
legend(
x = 1, y = 1.2, legend = LETTERS[1:5],
col = unique(cols), pch = 16, bty = "n", xpd = NA
)
par(op)
```
坐标轴标签 `xlab` 和 `ylab` 的内容很长的时候需要内边空
```{r}
par(cex.lab = 1.7)
plot(1, 1,
ylab = "A very very long axis title\nthat need special care",
xlab = "", type = "n"
)
# 增加内边空的大小
par(mar = c(5, 7, 4, 2))
plot(1, 1,
ylab = "A very very long axis title\nthat need special care",
xlab = "", type = "n"
)
```
有时候,仅仅增加内边空还不够,坐标轴标签内容甚至可以出现在绘图区域外面,设置 `outer = TRUE`
```{r}
par(oma = c(0, 4, 0, 0))
plot(1, 1, ylab = "", xlab = "", type = "n")
mtext(
text = "A very very long axis title\nthat need special care",
side = 2, line = 0, outer = TRUE, cex = 1.7
)
```
```{r,fig.cap="设置每个子图的边空 mar",fig.asp=1,title.mar=TRUE}
op <- par(
mfrow = c(2, 2),
oma = c(0, 0, 3, 0),
mar = c(3, 3, 4, 1) + .1 # Margins
)
for (i in 1:4) {
plot(runif(20), runif(20),
xlab = "", ylab = "",
main = paste("random plot (", i, ")", sep = "")
)
}
par(op)
mtext("Title",
side = 3, line = 1.5, font = 2, cex = 2, col = "red"
)
```
### 图层 {#base-layer}
覆盖图形 `add = T` or `par(new=TRUE)`
```{r,fig.cap="添加图层",fig.asp=0.8}
plot(runif(5), runif(5),
xlim = c(0, 1), ylim = c(0, 1)
)
points(runif(5), runif(5),
col = "#EA4335", pch = 16, cex = 3
)
lines(runif(5), runif(5), col = "red")
segments(runif(5), runif(5), runif(5), runif(5),
col = "blue"
)
title(main = "Overlaying points, segments, lines...")
```
### 布局 {#base-layout}
`layout` 函数布局, 绘制复杂组合图形
```{r,fig.cap="更加复杂的组合图形",fig.asp=1}
op <- par(oma = c(0, 0, 3, 0))
layout(matrix(c(
1, 1, 1,
2, 3, 4,
2, 3, 4
), nr = 3, byrow = TRUE))
hist(rnorm(n), col = "light blue")
hist(rnorm(n), col = "light blue")
hist(rnorm(n), col = "light blue")
hist(rnorm(n), col = "light blue")
mtext("The \"layout\" function",
side = 3, outer = TRUE,
font = 2, cex = 1.2
)
```
### 组合 {#base-combine}
`par` 之 `fig` 参数很神奇,使得多个图可以叠加在一起,它接受一个数值向量`c(x1, x2, y1, y2)` ,是图形设备显示区域中的绘图区域的(NDC, normalized device coordinates)坐标。
```{r,fig.cap="多图叠加",fig.asp=1,title.mar=TRUE}
plot(1:12,
type = "b", main = "'fg' : axes, ticks and box in gray",
fg = gray(0.7), bty = "7", sub = R.version.string
)
par(fig = c(1, 6, 5, 10) / 10, new = T)
plot(6:10,
type = "b", main = "",
fg = gray(0.7), bty = "7", xlab = R.version.string
)
```
`fig` 参数控制图形的位置,用来绘制组合图形
```{r,fig.cap="组合图形"}
n <- 1000
x <- rt(n, df = 10)
hist(x,
col = "light blue",
probability = "TRUE", main = "",
ylim = c(0, 1.2 * max(density(x)$y))
)
lines(density(x),
col = "red",
lwd = 3
)
op <- par(
fig = c(.02, .4, .5, .98),
new = TRUE
)
qqnorm(x,
xlab = "", ylab = "", main = "",
axes = FALSE
)
qqline(x, col = "red", lwd = 2)
box(lwd = 2)
par(op)
```
### 分屏 {#base-screen}
`split.screen` 分屏组合
```{r,fig.cap="分屏"}
random.plot <- function() {
N <- 200
f <- sample(
list(
rnorm,
function(x) {
rt(x, df = 2)
},
rlnorm,
runif
),
1
) [[1]]
x <- f(N)
hist(x, col = "lightblue", main = "", xlab = "", ylab = "", axes = F)
axis(1)
}
op <- par(bg = "white", mar = c(2.5, 2, 1, 2))
split.screen(c(2, 1))
split.screen(c(1, 3), screen = 2)
screen(1)
random.plot()
# screen(2); random.plot() # Screen 2 was split into three screens: 3, 4, 5
screen(3)
random.plot()
screen(4)
random.plot()
screen(5)
random.plot()
close.screen(all = TRUE)
par(op)
```
### 交互 {#identify-locator}
辅助绘图 identify locator
## 基础统计图形 {#base-graphics}
按图的类型划分,最后在小结部分给出各图适用的数据类型
根据数据类型划分: 对于一元数据,可用什么图来描述;多元数据呢,连续数据和离散数据(分类数据)
先找一个不重不漏的划分,指导原则是根据数据类型选择图,根据探索到的数据中的规律,选择图
其它 assocplot fourfoldplot sunflowerplot
### 条形图 {#plot-bar}
[条形图](https://rpubs.com/chidungkt/392980)
简单条形图
```{r diamonds-base-barplot,fig.cap='条形图'}
data(diamonds, package = "ggplot2") # 加载数据
par(mar = c(2, 5, 1, 1))
barCenters <- barplot(table(diamonds$cut),
col = "lightblue", axes = FALSE,
axisnames = FALSE, horiz = TRUE, border = "white"
)
text(
y = barCenters, x = par("usr")[3],
adj = 1, labels = names(table(diamonds$cut)), xpd = TRUE
)
axis(1,
labels = seq(0, 25000, by = 5000), at = seq(0, 25000, by = 5000),
las = 1, col = "gray"
)
grid()
```
简单柱形图
```{r,fig.cap="柱形图"}
set.seed(123456)
barPois <- table(stats::rpois(1000, lambda = 5))
plot(barPois, col = "lightblue", type = "h", lwd = 10, main = "")
box(col = "gray")
```
复合条形图
```{r barplot-VADeaths-1,fig.cap="复合条形图"}
par(mar = c(4.1, 2.1, 0.5, 4.5))
barplot(VADeaths,
border = "white", horiz = FALSE, col = hcl.colors(5),