A ggplot2 Tutorial for Beautiful Plotting in R
原文见https://cedricscherer.netlify.com/2019/08/05/a-ggplot2-tutorial-for-beautiful-plotting-in-r/
引言
从2016年开始,我不得不准备博士工作介绍的讲演,因为非常讨厌R
的基础绘图包的语法和样式,从那时起开始用ggplot2
来可视化我的数据。因为时间不够,我试了n次错用于绘制这些图形 ,还用了大量的谷歌搜索的帮助。我经常回顾的资源是篇博客文章Beautiful plotting in R: A ggplot2 cheatsheet ,作者是 Zev Ross, 2014年8月4日发布,最后更新于2016年1月。归功于这个博客文章,我的演讲中包含了很多非常优美的图形。我决定把这篇教程逐步予以介绍。我从中获益良多,从直接修改代码开始,与时俱进,增加了很多代码段、图表类型和资源。
由于Zev Ross 的博客很多年没有更新了,我在自己的Github上有跟新版(最后更新于2017年1月)。在此主页是最合适的地方(另外,我添加了多处更新,如精彩绝伦的patchwork
和ggforce
包。还有饼图,因为人人都爱looooves饼图!)
以下是我做的主要修改:
- 遵循R的规范格式,如 Hadley Wickham, Google 或 Coding Club 指导格式),
- 改变了图形的样式和外观(如不仅仅做了些许改变,我改变了所有绘图的轴标题、图例和漂亮的颜色),
- 更新的版本在
ggplot2
中记录了这些变化, - 修改了输入的数据 (GitHub 资源),
- 为实战练习和研讨会准备了可执行的R脚本,
- 加入了额外的小提示,如:
- 另外的绘图类型 (例如轮廓图、地毯图、屋脊图)
- 如何和为什么使用Viridis调色板
- 使用 Tufte 打印样式创建最小绘图
- 如何调整绘图标题、副标题和标题
- 如何为图形加入不同的线型
- 如何在图例和图例项名称改变顺序
- 如何为数据添加标签(如何做的更美观)
目录
点击进入英文原文链接,哈哈哈!!!
- Preparation
- The Dataset
- The
ggplot2
Package - A Default ggplot
- Working with Axes
- Working with Titles
- Working with Legends
- Working with Backgrounds & Grid Lines
- Working with Margins
- Working with Multi-Panel Plots
- Working with Themes
- Working with Colors
- Working with Lines
- Working with Text
- Working with Coordinates
- Working with Chart Types
- Working with Ribbons (AUC, CI, etc.)
- Working with Smoothings
- Working with Interactive Plots
Preparation(准备)
- 用着这个链接下载数据 这里.
- 带有可执行代码的 Rmarkdwon 脚本在下载 here.
- 以下是需要安装的包:
- ggplot2
- ggthemes
- tidyverse
- extrafont
- patchwork
- cowplot
- grid
- gridExtra
- ggrepel
- reshape2
- ggforce
- ggridges
- shiny
install.packages(c("ggplot2", "ggthemes", "tidyverse", "extrafont",
"cowplot", "grid", "gridExtra", "ggrepel",
"reshape2", "ggforce", "ggridges", "shiny"))
devtools::install_github("thomasp85/patchwork")
(出于教学目的,在任何一个绘图章节中,除了个ggplot2之外,在相应的代码块中都加载了必要的R包)
The Dataset(数据集)
我们采用的数据来源于 National Morbidity and Mortality Air Pollution Study (NMMAPS)。为了使图形可控,我们把数据限定于芝加哥和1997-2000。更多的数据细节,参考Roger Peng的图书 Statistical Methods in Environmental Epidemiology with R.
chic <- readr::read_csv("https://raw.githubusercontent.com/Z3tt/R-Tutorials/master/ggplot2/chicago-nmmaps.csv")
tibble::glimpse(chic)
## Observations: 1,461
## Variables: 10
## $ city "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic", "chic"...
## $ date 1997-01-01, 1997-01-02, 1997-01-03, 1997-01-04, 1997-01-05, 1997-01-06, 1997-01-07, 1997-01-08, 1997-01-09, 1997-01-10, 1997-01-11, 1997-01-12, 1997-01-13, 1997-01-14, 1997-01-15, 1997-01-16, 1997-01-17, 1997-01-18, 1997-01-19, 1997-01-20, 1997-01-21, 1997-01-22, 1997-01-23, 1997-01-24, 1997-01-25, 1997-01-26, 1997-01-27, 1997-01-28, 1997-01-29, 1997-01-30, 1997-01-31, 1997-02-01, 1997-02-02, 1997-02-03, 1997-02-04, 1997-02-05, 1997-02-06, 1997-02-07, 1997-02-08, 1997-02-09, 1997-02-10, 1997-02-11, 1997-02-12, 1997-02-13, 1997-02-14, 1997-02-15, 1997-02-16, 1997-02-17, 1997-02-18, 1997-02-19, 1997-02-20, 1997-02-21, 1997-02-22, 1997-02-23, 1997-02-24, 1997-02-25, 1997-...
## $ death 137, 123, 127, 146, 102, 127, 116, 118, 148, 121, 110, 127, 129, 151, 128, 132, 116, 142, 124, 124, 127, 121, 134, 120, 109, 109, 115, 105, 114, 120, 117, 126, 97, 96, 119, 125, 116, 118, 121, 114, 111, 107, 127, 98, 104, 122, 124, 120, 106, 103, 139, 133, 109, 121, 111, 105, 107, 123, 124, 125, 108, 114, 104, 120, 134, 101, 102, 125, 119, 115, 121, 112, 127, 99, 125, 115, 113, 105, 113, 120, 105, 119, 147, 123, 108, 117, 110, 106, 96, 119, 119, 99, 120, 130, 97, 105, 102, 104, 137, 111, 108, 96, 100, 105, 128, 120, 98, 118, 94, 117, 121, 110, 110, 108, 121, 114, 116, 109, 123, 115, 101, 118, 100, 126, 126, 121, 114, 112, 111, 111, 107, 124, 104, 107, 109, 133, 108, 109...
## $ temp 36.0, 45.0, 40.0, 51.5, 27.0, 17.0, 16.0, 19.0, 26.0, 16.0, 1.5, 1.0, 3.0, 10.0, 19.0, 9.5, -3.0, 0.0, 14.0, 31.0, 35.0, 36.5, 26.0, 32.0, 14.5, 11.0, 17.0, 2.0, 8.0, 16.5, 31.5, 35.0, 36.5, 30.0, 34.5, 30.0, 26.0, 25.5, 25.5, 26.0, 27.0, 23.5, 21.0, 20.5, 25.5, 20.0, 18.5, 30.0, 48.5, 37.5, 35.5, 36.0, 26.0, 28.0, 21.5, 25.5, 36.5, 34.5, 37.5, 45.5, 35.0, 33.5, 38.0, 33.0, 26.5, 35.5, 39.0, 37.0, 44.0, 37.0, 33.5, 37.5, 26.5, 19.0, 24.5, 45.0, 33.5, 35.5, 46.0, 53.5, 37.5, 32.5, 33.0, 40.5, 44.0, 60.5, 55.5, 43.5, 37.5, 38.5, 44.5, 53.0, 59.5, 62.5, 60.5, 45.0, 34.0, 28.5, 30.0, 30.5, 33.5, 33.5, 38.5, 41.5, 49.0, 43.0, 40.5, 40.0, 45.5, 49.0, 45.0, 43.0, 48.5, 47.5, 4...
## $ dewpoint 37.50000, 47.25000, 38.00000, 45.50000, 11.25000, 5.75000, 7.00000, 17.75000, 24.00000, 5.37500, -6.62500, -8.87500, 1.50000, 11.50000, 23.25000, -9.75000, -10.37500, -4.12500, 22.62500, 27.25000, 41.62500, 20.75000, 18.75000, 29.50000, -1.37500, 17.12500, 8.37500, -6.37500, 11.00000, 16.37500, 33.75000, 29.66667, 29.62500, 28.00000, 32.00000, 24.25000, 21.87500, 23.37500, 22.50000, 21.00000, 21.75000, 19.50000, 11.60000, 16.37500, 23.00000, 15.25000, 8.12500, 32.62500, 41.37500, 27.50000, 44.12500, 29.62500, 24.25000, 14.62500, 10.87500, 27.12500, 35.00000, 30.25000, 36.00000, 44.00000, 27.37500, 29.37500, 28.87500, 28.62500, 13.37500, 35.25000, 28.25000, 32.62500, 33....
## $ pm10 13.052268, 41.948600, 27.041751, 25.072573, 15.343121, 9.364655, 20.228428, 33.134819, 12.118381, 24.761534, 18.126151, 16.013770, 34.991079, 64.945403, 26.941955, 27.022906, 18.837025, 31.859740, 30.923168, 19.894566, 27.882017, 18.508762, 11.845698, 26.687346, 16.612825, 21.641455, 22.672498, 28.101180, 51.776607, 48.741462, 24.686329, 23.784943, 27.762150, 21.600928, 17.050900, 10.157749, 15.943086, 33.010704, 14.955909, 30.410449, 23.914813, 22.972347, 12.712336, 22.719836, 35.676001, 28.373076, 15.662430, 38.744847, 27.597166, 17.612211, 29.768805, 7.340321, 7.856717, 7.908915, 17.834350, 41.124012, 34.052583, 19.749350, 26.126759, 28.129506, 9.940940, 15.980970, 2...
## $ o3 5.659256, 5.525417, 6.288548, 7.537758, 20.760798, 14.940874, 11.920985, 8.678477, 13.355892, 10.448264, 15.866094, 15.115290, 9.381068, 8.029508, 7.066111, 20.113023, 15.363898, 12.713223, 9.616133, 16.840369, 12.758676, 21.024213, 18.665072, 7.131938, 17.167861, 9.960118, 9.167350, 13.613967, 7.945009, 7.660619, 11.882608, 16.676182, 12.032368, 21.849559, 10.887549, 14.894031, 15.957824, 14.391243, 19.749645, 12.397635, 14.193562, 20.492388, 23.091993, 20.171005, 15.453240, 19.526661, 20.019234, 17.297562, 27.013275, 19.055436, 6.890252, 16.313610, 23.015853, 24.990318, 18.939318, 12.526243, 7.962753, 13.194153, 15.178614, 13.860717, 30.992349, 29.260852, 15.413875, 1...
## $ time 3654, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662, 3663, 3664, 3665, 3666, 3667, 3668, 3669, 3670, 3671, 3672, 3673, 3674, 3675, 3676, 3677, 3678, 3679, 3680, 3681, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 3696, 3697, 3698, 3699, 3700, 3701, 3702, 3703, 3704, 3705, 3706, 3707, 3708, 3709, 3710, 3711, 3712, 3713, 3714, 3715, 3716, 3717, 3718, 3719, 3720, 3721, 3722, 3723, 3724, 3725, 3726, 3727, 3728, 3729, 3730, 3731, 3732, 3733, 3734, 3735, 3736, 3737, 3738, 3739, 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, 3748, 3749, 3750, 3751, 3752, 3753, 3754, 3755, 3756, 3757, 3758, 3759, 3760, 3761, 3762, 3763, 3764, 3765, 3766, ...
## $ season "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter", "Winter"...
## $ year 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, 1997, ...
head(chic, 10)
## # A tibble: 10 x 10
## city date death temp dewpoint pm10 o3 time season year
##
## 1 chic 1997-01-01 137 36 37.5 13.1 5.66 3654 Winter 1997
## 2 chic 1997-01-02 123 45 47.2 41.9 5.53 3655 Winter 1997
## 3 chic 1997-01-03 127 40 38 27.0 6.29 3656 Winter 1997
## 4 chic 1997-01-04 146 51.5 45.5 25.1 7.54 3657 Winter 1997
## 5 chic 1997-01-05 102 27 11.2 15.3 20.8 3658 Winter 1997
## 6 chic 1997-01-06 127 17 5.75 9.36 14.9 3659 Winter 1997
## 7 chic 1997-01-07 116 16 7 20.2 11.9 3660 Winter 1997
## 8 chic 1997-01-08 118 19 17.8 33.1 8.68 3661 Winter 1997
## 9 chic 1997-01-09 148 26 24 12.1 13.4 3662 Winter 1997
## 10 chic 1997-01-10 121 16 5.38 24.8 10.4 3663 Winter 1997
The ggplot2
Package(ggplot2包)
ggplot2
是个以声明方式创建图形的系统,基于此书 The Grammar of Graphics。你需要提供数据,告诉ggplot2
如何把变量映射到美学外观、使用何种图形属性,细节问题由ggplot2处理。
随后,一幅ggplot图被从几个基本原件所创建:
1.数据:
用于绘图的原始数据The raw data that you want to plot.
2.几何形状 geom_:
表示数据的几何图形。
3.美学外观 aes()_:
几何和统计对象的美学外观,如颜色、大小、形状、透明度和位置。
4.标度 scale_:
在数据和美学维度间进行映射,如数据范围到绘图宽度或赋予颜色的因数。
5.统计变换 stat_:
数据的统计汇总,分位数、拟合曲线和总和。
6.坐标系 coord_:
用于将数据坐标映射到数据矩形平面的转换。
7分面 facet_:
把数据分列成图形网格。
8.视觉主题 theme()
:
图形的总体视觉默认效果,如背景、网格、坐标轴、默认字体、大小和颜色。
A Default ggplot(默认的ggplot)
首先,我们加载 ggplot2
包 (也能通过 tidyverse包加载):
library(ggplot2)
#library(tidyverse)
ggplot2 的语法体系有别于基本R绘图包。如前所示,我们经常开始通过 ggplot(data = df, aes(x = 变量1, y = 变量2)) 定义绘图原件,它告诉ggplot2我们用此数据开始工作。因而,运行这个命令,只创建了一个绘图板,因为ggplot2不知道我们想怎样用这个数据进行绘图。
(g <- ggplot(chic, aes(x = date, y = temp)))
提示: 在创建图形时,用括号创建一个对象,将即刻输出对象(而不是写作g <- ggplot(...) ,然后 g)。
让我们告诉 ggplot想用的样式:
g + geom_point()
别担心,我们将在后面学习几个绘图类型。
Change Color of Points(改变点的颜色)
用这个命令,可以改变美学外观,如改变点的颜色:
g + geom_point(color = "firebrick")
把其用之于我们的绘图原件,以下基于g的图形就有了红色点。
通过设置一个不同内置的主题,如theme_bw,我们就去除了默认的灰色系的外观。
theme_set(theme_bw())
g + geom_point(color = "firebrick")
(能在 “Working with Themes”部分找到怎样使用内置主题和怎样定制主题。)
Working with Axes(坐标轴)
加入坐标轴标签
让我们为坐标轴加入写好的标签
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Year", y = expression(paste("Temperature (", degree ~ F, ")")))
Move Labels Away from the Plot & Change Color(从图形中移动标签和改变标签颜色)
theme()
是一个必要的命令用于修改各种主题元素(文本和标题,框线、符号、背景等)。我们将大量使用它,参见可能的外观here.
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Year", y = "Temperature (°F)") +
theme(axis.title.x = element_text(color = "sienna",
size = 15, vjust = -0.35),
axis.title.y = element_text(color = "orangered",
size = 15, vjust = 0.35))
Change Size & Angle of Tick Text(改变文本的大小和角度)
用angle和vjust调整文本的位置(0=左对齐,0.5=中心对齐,1=右对齐):
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Year", y = "Temperature (°F)") +
theme(axis.text.x = element_text(angle = 50, size = 16,
vjust = 0.5))
Remove Axis Ticks & Tick Text(去除坐标轴刻度和刻度文本)
很少有理由去这么做-但是要这么做就需要这样来:
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())
如果你想去掉主体元素,参数的元素就是
element_blank()
。
Limit Axis Range(限制坐标轴范围)
有时候想要缩放你的数据,可以这样做,而不需要从数据取子集。
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Year", y = "Temperature (°F)") +
ylim(c(0, 50))
另外,可用g + scale_x_continuous(limits = c(0, 50))
或者g + coord_cartesian(xlim = c(0, 50))
。前者移除了范围以外的所有的数据点,而第二个调整了可视的范围。
Force Plot to Start at Origin(强制绘图开始于原点)
与之相关,可以强制R绘图开始于原点:
library(tidyverse)
chic %>%
dplyr::filter(temp > 25, o3 > 20) %>%
ggplot(aes(x = temp, y = o3)) +
geom_point() +
labs(x = expression(paste("Temperature higher than 25 ", degree ~ F, "")),
y = "Ozone higher than 20 ppb") +
expand_limits(x = 0, y = 0)
用
coord_cartesian(xlim = c(0, max(chic_red$temp)), ylim = c(0, max(chic_red$o3)))
能得到相同的结果。
也能真正的强制绘图开始于原点。
chic %>%
dplyr::filter(temp > 25, o3 > 20) %>%
ggplot(aes(x = temp, y = o3)) +
geom_point() +
labs(x = expression(paste("Temperature higher than 25 ", degree ~ F, "")),
y = "Ozone higher than 20 ppb") +
expand_limits(x = 0, y = 0) +
scale_x_continuous(expand = c(0, 0)) +
scale_y_continuous(expand = c(0, 0)) +
coord_cartesian(clip = "off")
Axes with Same Scaling(带有相同标度的坐标)
出于展示的目的,我们用温度和带有随机噪声的温度绘图:
ggplot(chic, aes(x = temp, y = temp + rnorm(nrow(chic), sd = 20))) +
geom_point() +
labs(x = "Temperature (°F)") +
xlim(c(0, 100)) + ylim(c(0, 150)) +
coord_equal()
Use a Function to Alter Labels(用函数改变标签)
有时要稍稍改变标签,或者加入单位或百分比符号,而不把他们加入你的数据。这种情况下,可以用一个函数来实现。这是一个例子:
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Year", y = "Temperature (°F)") +
scale_y_continuous(label = function(x) {return(paste(x, "Degrees Fahrenheit"))})
Working with Titles(标题)
Add a Title(加入标题)
能用ggtitle()
函数加入标题:
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Year", y = "Temperature (°F)") +
ggtitle("Temperatures in Chicago")
此外,可以用g + labs(tite = "Temperatures in Chicago")
。这里可以加入几个参数,如加入副标题和一个标题:
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")
Make Title Bold & Add a Space at the Baseline(将标题加粗和基线加入空格)
face参数能用于使字体加粗或斜体。margin参数用 margin函数提供上下左右的边界(默认单位是点)。
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Year", y = "Temperature (°F)",
title = "Temperatures in Chicago") +
theme(plot.title = element_text(size = 15, face = "bold",
margin = margin(10, 0, 10, 0)))
(记住边界参数的好方法是“trouble”的trbl字母与四个边很像)。
Adjust Position of Titles(调整标题的位置)
用hjust
控制对齐(代表水平调整):
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Year", y = "Temperature (°F)",
title = "Temperatures in Chicago") +
theme(plot.title = element_text(size = 15, face = 4, hjust = 1))
当然,用
vjust
可以调节垂直对齐。
Use a Non-Traditional Font in Your Title(在题目中用非传统的字体)
值得注意的是可以用不同的字体。为了用安装到你机器上的字体(可能你在用office程序),我们从extrafont包获取帮助。在加载包后,需要输入和加载安装到你机器上的:
library(extrafont)
extrafont::font_import()
## Importing fonts may take a few minutes, depending on the number of fonts and the speed of the system.
## Continue? [y/n]
## extrafont::loadfonts(device = "win")
可以先看一下你输入的字体库,用fonts()
或 fonttable()
.
现在,我们使用这些字体家族的一种:
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Year", y = "Temperature (°F)", title = "Temperatures in Chicago") +
theme(plot.title = element_text(size = 18, family = "Merriweather"))
(你也可以为你的图形设置一种非默认的字体,详见“Working with Themes”部分。我用Roboto Condensed作为图形的新的默认字体)
theme_set(theme_bw(base_size = 12, base_family = "Roboto Condensed"))
Change Spacing in Multi-Line Text(在多行文本中改变间隔)
能用 lineheight 参数改变行的间隔。在本例中,我把行压缩了一点(行高小于1)。
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Year", y = "Temperature (°F)") +
ggtitle("Temperatures in Chicago\nfrom 1997 to 2001") +
theme(plot.title = element_text(size = 16, face = "bold",
vjust = 1, lineheight = 0.75))
Working with Legends(图例)
我们将按照季节为图形着色。你会看到默认情况下,图例的标题正是我们在颜色参数所定义的:
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)")
Turn Off the Legend(关闭图例)
常被问及的第一个问题是:“我怎样才能去掉图例?”。
很容易就能用legend.position = "none"
实现:
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
theme(legend.position = "none")
取决于特定的情况,也可以用guides(fill = F)
或者用scale_fill_discrete(guide = F)
。
Turn Off Legend Titles(关闭图例标题)
正如我们所学,用 element_blank()
来绘制无图(nothing):
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
theme(legend.title = element_blank())
Change Legend Position(改变图例位置)
如不想把图例置于右侧,可在用theme
中legend.position
参数 :
gplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
theme(legend.position = "bottom")
可能的位置包括:上,右,下,左。
Change Style of Legend Titles(改变图例标题的样式)
通过调节主题元素legend.title
修改图例题目的外观:
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
theme(legend.title = element_text(color = "chocolate",
size = 14, face = "bold"))
Change Legend Title(改变图例标题)
改变图例标题最简便的方式是使用labs参数:
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)", color = "Seasons\nindicated\nby colors:") +
theme(legend.title = element_text(color = "chocolate",
size = 14, face = "bold"))
取决于展示变量的类型,图例的细节可通过
scale_color_discrete
或
scale_color_continuous
修改。
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
theme(legend.title = element_text(color = "chocolate",
size = 14, face = "bold")) +
scale_color_discrete(name = "Seasons\nindicated\nby colors:")
Change Order of Legend Keys(改变图例的排序)
通过改变season的水平达到目的 :
chic$season <- factor(chic$season, levels = c("Spring", "Summer",
"Autumn", "Winter"))
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)")
Change Legend Labels(改变图例标签)
我们实现以其涵盖的月份替换季节标签:
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
theme(legend.title = element_text(color = "chocolate",
size = 14, face = 2)) +
scale_color_discrete("Seasons:", labels = c("Mar - May", "Jun - Aug",
"Sep - Nov", "Dec - Feb"))
Change Background Boxes in the Legend(改变图例的背景边框)
要改变(填充)图例项的背景色,我们需要调整主题元素legend.key
的设置:
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
theme(legend.key = element_rect(fill = "darkgoldenrod1"),
legend.title = element_text(color = "chocolate",
size = 14, face = 2)) +
scale_color_discrete("Seasons:")
如果要全部去除背景,使用fill = NA
。
Change Size of Legend Symbols(改变图例符号)
图例中的点有点损失,特别是没有边框时。覆盖默认的点,试试以下代码:
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
theme(legend.key = element_rect(fill = NA),
legend.title = element_text(color = "chocolate",
size = 14, face = 2)) +
scale_color_discrete("Seasons:") +
guides(color = guide_legend(override.aes = list(size = 6))
Leave a Layer Off the Legend(只在图例中保留一个图层)
假如你有一个点状图层,接着你又为同样的数据添加了一个边际图。默认情况下,点图和线图使得图例变成这样:
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
geom_rug() +
theme(legend.title = element_text(color = "chocolate",
size = 14, face = 2)) +
scale_color_discrete("Seasons:")
可用
show.legend = F
来关闭图例的一个图层:
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
geom_rug(show.legend = F) +
theme(legend.title = element_text(color = "chocolate", size = 14, face = 2)) +
scale_color_discrete("Seasons:")
Manually Adding Legend Items(手动添加图例项)
ggplot2
不能自动添加图例,除非你来把美学参数(颜色、大小等)映射到一个变量。我曾不止一次的想有一个图例,使得所绘之图更加清晰。
这是默认图形:
ggplot(chic, aes(x = date, y = o3)) +
geom_line(color = "gray") +
geom_point(color = "darkorange2") +
labs(x = "Year", y = "Ozone")
我们可以强制映射一个图例到一个变量。用 aes()
映射线和点。在此我们的数据集中,不映射到一个变量,而是映射到一个代码串(以便为每一个线或点绘制一种颜色)。
ggplot(chic, aes(x = date, y = o3)) +
geom_line(aes(color = "line")) +
geom_point(aes(color = "points")) +
labs(x = "Year", y = "Ozone") +
scale_color_discrete("Type:")
已经接近,但是这不是我们想要的。我们想要灰色和红色。要改变颜色,我们使用scale_color_manual()
。另外,使用 guide()
函数覆盖图例外观。
Voila! 现在,我们绘出了灰色的线和红色的点,还有带有灰色线和红色点的图例符号:
ggplot(chic, aes(x = date, y = o3)) +
geom_line(aes(color = "line")) +
geom_point(aes(color = "points")) +
labs(x = "Year", y = "Ozone") +
scale_color_manual("", guide = "legend",
values = c("points" = "darkorange2",
"line" = "gray")) +
guides(color = guide_legend(override.aes = list(linetype = c(1, 0),
shape = c(NA, 16))))
Working with Backgrounds & Grid Lines(背景和网格线)
有很多种方法用一个函数(如下)改变绘图的整体外观,但是如果你只想改变部分元素的颜色,你可以这么做。
Change the Panel Color(改变面板颜色)
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Year", y = "Temperature (°F)") +
theme(panel.background = element_rect(fill = "moccasin"))
Change Grid Lines(改变网格线)
有两种网格线:主要网格线指示刻度和在主要网格线之间的次要网格线。
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Year", y = "Temperature (°F)") +
theme(panel.background = element_rect(fill = "grey90"),
panel.grid.major = element_line(color = "gray10", size = 0.5),
panel.grid.minor = element_line(color = "gray70", size = 0.25))
进一步,你可以在主要网格线和次要网格线间自定义间隔:
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))
Change the Plot Background Color(改变图形的背景色)
要改变(填充)图形区域的背景色,需要调节主题元素的 plot.background
:
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "firebrick") +
labs(x = "Year", y = "Temperature (°F)") +
theme(plot.background = element_rect(fill = "gray60"))
Working with Margins(边界)
有时候为绘图边界加入一点空隙是有用的。同前面的例子相似,我们用theme()
函数的参数实现。在此使用参数 plot.margin
. 如前,我们通过plot.background改变背景色,已经展示了默认的边际。
现在,让我们为左右添加额外的空间。参数plot.margin
可以处理多种不同的单位(厘米、英寸等),但是需要使用 grid
包的函数单位来定义单位。在此我在左右使用用5厘米的边际。
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 = unit(c(1, 5, 1, 5), "cm"))
边际的顺序是上右下左。一个容易记忆的方法是 "trouble 分别代表四个边的首字母。
Working with Multi-Panel Plots(分面绘图)
ggplot2
包有两个很好的函数用于创建分面绘图。他们相互有联系,但是有所不同,facet_wrap
本质上基于一个变量创建了一个绘图带,而facet_grid
可以接受两个变量。
Create a Single Row of Plots Based on One Variable(基于一个变量创建一列图形)
facet_wrap
创建一个变量的分面图,前面用一个破折号: facet_wrap(~ variable)
。子图的外观用 ncol
和 nrow
参数进行控制:
g <- ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "chartreuse4") +
labs(x = "Year", y = "Temperature (°F)")
g + facet_wrap(~ year, nrow = 1) +
theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1))
Create a Matrix of Plots Based on One Variable(基于一个变量创建绘图矩阵)
g + facet_wrap(~ year, nrow = 2)
Allow Scales to Roam Free(自由展示标度)
ggplot2
分面图的默认效果是为各自分面图使用相同的标度。但有时你想让自己的数据的每个分面有自己的标度。这不是个好主意,因为这会给用户对数据以错误的印象。你可以设置scales = "free"
来实现:
g + facet_wrap(~ year, nrow = 2, scales = "free")
注意x和y轴的范围是不同的。
Create a Grid of Plots Based on Two Variables(基于两个变量创建一个绘图矩阵)
在两个变量的情况下,facet_grid
可以完成此任务。在此,变量的顺序决定了行数和列数:
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "orangered") +
theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) +
labs(x = "Year", y = "Temperature (°F)") +
facet_grid(year ~ season)
要交换行对列的排布,可以改变 facet_grid(year ~ season)
为 facet_grid(season ~ year)
。
Put Two (Different) Plots Side by Side(把两张图肩靠肩排列)
有好几种方法来组合绘图。以我愚见,最简便的方法是 patchwork
包 ,
Thomas Lin Pedersen写的:
p1 <- ggplot(chic, aes(x = date, y = temp,
color = factor(season))) +
geom_point() +
geom_rug() +
labs(x = "Year", y = "Temperature (°F)")
p2 <- ggplot(chic, aes(x = date, y = o3)) +
geom_line(color = "gray") +
geom_point(color = "darkorange2") +
labs(x = "Year", y = "Ozone")
library(patchwork)
p1 + p2
通过两图相除,可以改变图的顺序(注意此排列方式,一个有图例而另一个没有图例):
p1 / p2
而且嵌套作图也是可以滴!
(g + p2) / p1
(注意图的排布,甚至只有一行包含图例)
另外,Claus Wilke写的 cowplot
包 提供了同样的功能(以及其它许多好的应用):
library(cowplot)
plot_grid(p1, p2)
… gridExtra
包也可以:
library(gridExtra)
grid.arrange(p1, p2, ncol = 2)
Working with Themes(主题)
Change the Overall Plotting Style(改变整体的绘图格式)
通过应用主题可以改变整体外观。例如,Jeffrey Arnold把 ggthemes
库和几个用户定义的主题放到一起。清单参见 ggthemes
网站. 不用任何代码,你就可以调节数种样式,其中一些样式和美学外观为大众所熟知。
这里是一个例子复制了《经济学人》杂志的绘图样式 :
library(ggthemes)
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
ggtitle("Ups and Downs of Chicago's Daily Temperatures") +
theme_economist() +
scale_color_economist(name = "Seasons:") +
theme(legend.title = element_text(size = 12, face = "bold"))
另外一个例子是Tufte的绘图样式,这是一个基于 Edward Tufte的书 The Visual Display of Quantitative Information的最少笔墨主题。 此书以 Minard’s chart depicting Napoleon’s march on Russia 作为有史以来人类所创建的最好的统计学绘图得以广为人知。Tuftes 图变的知名是由于纯粹的样式。请看你自己的图:
set.seed(2019)
chic.red <- chic[sample(nrow(chic), 50), ]
ggplot(chic.red, aes(x = temp, y = o3)) +
geom_point() +
labs(x = "Temperature (°F)", y = "Ozone") +
ggtitle("Temperature and Ozone Levels in Chicago") +
theme_tufte() +
stat_smooth(method = "lm", col = "black", size = 0.7,
fill = "gray60", alpha = 0.2)
由于Tufte’s样式是极简主义,我们首先减少用于展示的数据点的数目以贴合这条规则。(不关心`stat_smooth() '命令,稍后我会解释)。只是添加它以使绘图更具趣味。
ggplot(chic.red, aes(x = temp, y = o3)) +
geom_point() +
labs(x = "Temperature (°F)", y = "Ozone") +
ggtitle("Temperature and Ozone Levels in Chicago") +
theme_tufte() +
stat_smooth(method = "lm", col = "black", size = 0.7,
fill = "gray60", alpha = 0.2) +
geom_rangeframe()
如果你想如此绘图,请参见此 博客,用R重绘几个Tufte 图。
Change the Size of All Plot Text Elements(改变所有绘图文本元素的大小)
很容易就一次性改变所有的文本元素的大小。如果你仔细研究默认的主题(见如下“Create and Use Your Custom Theme”章节),就会注意到所有的元素的大小都相对于基本的大小。所以,你可以简单改变基本大小,如果你想增加绘图的可读性:
theme_set(theme_gray(base_size = 30, base_family = "Roboto Condensed"))
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
guides(color = F)
Create and Use Your Custom Theme(用户自定义的主题的创建和使用)
如果想要改变整体主题,可以用 theme_set
,例如theme_set(theme_bw())
。默认的主题是theme_gray
。如果要创建自定义的主题,可以从灰度主题提取代码并修改。注意 rel()
函数改变了base_size
的大小。
theme_gray
ize = 11, base_family = "", base_line_size = base_size/22,
## base_rect_size = base_size/22)
## {
## half_line <- base_size/2
## theme(line = element_line(colour = "black", size = base_line_size,
## linetype = 1, lineend = "butt"), rect = element_rect(fill = "white",
## colour = "black", size = base_rect_size, linetype = 1),
## text = element_text(family = base_family, face = "plain",
## colour = "black", size = base_size, lineheight = 0.9,
## hjust = 0.5, vjust = 0.5, angle = 0, margin = margin(),
## debug = FALSE), axis.line = element_blank(), axis.line.x = NULL,
## axis.line.y = NULL, axis.text = element_text(size = rel(0.8),
## colour = "grey30"), axis.text.x = element_text(margin = margin(t = 0.8 *
## half_line/2), vjust = 1), axis.text.x.top = element_text(margin = margin(b = 0.8 *
## half_line/2), vjust = 0), axis.text.y = element_text(margin = margin(r = 0.8 *
## half_line/2), hjust = 1), axis.text.y.right = element_text(margin = margin(l = 0.8 *
## half_line/2), hjust = 0), axis.ticks = element_line(colour = "grey20"),
## axis.ticks.length = unit(half_line/2, "pt"), axis.ticks.length.x = NULL,
## axis.ticks.length.x.top = NULL, axis.ticks.length.x.bottom = NULL,
## axis.ticks.length.y = NULL, axis.ticks.length.y.left = NULL,
## axis.ticks.length.y.right = NULL, axis.title.x = element_text(margin = margin(t = half_line/2),
## vjust = 1), axis.title.x.top = element_text(margin = margin(b = half_line/2),
## vjust = 0), axis.title.y = element_text(angle = 90,
## margin = margin(r = half_line/2), vjust = 1), axis.title.y.right = element_text(angle = -90,
## margin = margin(l = half_line/2), vjust = 0), legend.background = element_rect(colour = NA),
## legend.spacing = unit(2 * half_line, "pt"), legend.spacing.x = NULL,
## legend.spacing.y = NULL, legend.margin = margin(half_line,
## half_line, half_line, half_line), legend.key = element_rect(fill = "grey95",
## colour = "white"), legend.key.size = unit(1.2, "lines"),
## legend.key.height = NULL, legend.key.width = NULL, legend.text = element_text(size = rel(0.8)),
## legend.text.align = NULL, legend.title = element_text(hjust = 0),
## legend.title.align = NULL, legend.position = "right",
## legend.direction = NULL, legend.justification = "center",
## legend.box = NULL, legend.box.margin = margin(0, 0, 0,
## 0, "cm"), legend.box.background = element_blank(),
## legend.box.spacing = unit(2 * half_line, "pt"), panel.background = element_rect(fill = "grey92",
## colour = NA), panel.border = element_blank(), panel.grid = element_line(colour = "white"),
## panel.grid.minor = element_line(size = rel(0.5)), panel.spacing = unit(half_line,
## "pt"), panel.spacing.x = NULL, panel.spacing.y = NULL,
## panel.ontop = FALSE, strip.background = element_rect(fill = "grey85",
## colour = NA), strip.text = element_text(colour = "grey10",
## size = rel(0.8), margin = margin(0.8 * half_line,
## 0.8 * half_line, 0.8 * half_line, 0.8 * half_line)),
## strip.text.x = NULL, strip.text.y = element_text(angle = -90),
## strip.placement = "inside", strip.placement.x = NULL,
## strip.placement.y = NULL, strip.switch.pad.grid = unit(half_line/2,
## "pt"), strip.switch.pad.wrap = unit(half_line/2,
## "pt"), plot.background = element_rect(colour = "white"),
## plot.title = element_text(size = rel(1.2), hjust = 0,
## vjust = 1, margin = margin(b = half_line)), plot.subtitle = element_text(hjust = 0,
## vjust = 1, margin = margin(b = half_line)), plot.caption = element_text(size = rel(0.8),
## hjust = 1, vjust = 1, margin = margin(t = half_line)),
## plot.tag = element_text(size = rel(1.2), hjust = 0.5,
## vjust = 0.5), plot.tag.position = "topleft", plot.margin = margin(half_line,
## half_line, half_line, half_line), complete = TRUE)
## }
##
##
现在,让我们修改默认主题函数,并看看效果图:
theme_custom <- function (base_size = 12, base_family = "Roboto Condensed") {
half_line <- base_size/2
theme(line = element_line(color = "black", size = 0.5, linetype = 1, lineend = "butt"),
rect = element_rect(fill = "white", color = "black", size = 0.5, linetype = 1),
text = element_text(family = base_family, face = "plain", color = "black",
size = base_size, lineheight = 0.9, hjust = 0.5, vjust = 0.5,
angle = 0, margin = margin(), debug = F),
axis.line = element_blank(),
axis.line.x = NULL,
axis.line.y = NULL,
axis.text = element_text(size = base_size * 1.1, color = "gray30"),
axis.text.x = element_text(margin = margin(t = 0.8 * half_line/2), vjust = 1),
axis.text.x.top = element_text(margin = margin(b = 0.8 * half_line/2), vjust = 0),
axis.text.y = element_text(margin = margin(r = 0.8 * half_line/2), hjust = 1),
axis.text.y.right = element_text(margin = margin(l = 0.8 * half_line/2), hjust = 0),
axis.ticks = element_line(color = "gray30", size = 0.7),
axis.ticks.length = unit(half_line / 1.5, "pt"),
axis.title.x = element_text(margin = margin(t = half_line), vjust = 1,
size = base_size * 1.3, face = "bold"),
axis.title.x.top = element_text(margin = margin(b = half_line), vjust = 0),
axis.title.y = element_text(angle = 90, margin = margin(r = half_line),
vjust = 1, size = base_size * 1.3, face = "bold"),
axis.title.y.right = element_text(angle = -90, vjust = 0,
margin = margin(l = half_line)),
legend.background = element_rect(color = NA),
legend.spacing = unit(0.4, "cm"),
legend.spacing.x = NULL,
legend.spacing.y = NULL,
legend.margin = margin(0.2, 0.2, 0.2, 0.2, "cm"),
legend.key = element_rect(fill = "gray95", color = "white"),
legend.key.size = unit(1.2, "lines"),
legend.key.height = NULL,
legend.key.width = NULL,
legend.text = element_text(size = rel(0.8)),
legend.text.align = NULL,
legend.title = element_text(hjust = 0),
legend.title.align = NULL,
legend.position = "right",
legend.direction = NULL,
legend.justification = "center",
legend.box = NULL,
legend.box.margin = margin(0, 0, 0, 0, "cm"),
legend.box.background = element_blank(),
legend.box.spacing = unit(0.4, "cm"),
panel.background = element_rect(fill = "white", color = NA),
panel.border = element_rect(color = "gray30",
fill = NA, size = 0.7),
panel.grid.major = element_line(color = "gray90", size = 1),
panel.grid.minor = element_line(color = "gray90", size = 0.5,
linetype = "dashed"),
panel.spacing = unit(base_size, "pt"),
panel.spacing.x = NULL,
panel.spacing.y = NULL,
panel.ontop = F,
strip.background = element_rect(fill = "white", color = "gray30"),
strip.text = element_text(color = "black", size = base_size),
strip.text.x = element_text(margin = margin(t = half_line,
b = half_line)),
strip.text.y = element_text(angle = -90, margin = margin(l = half_line,
r = half_line)),
strip.placement = "inside",
strip.placement.x = NULL,
strip.placement.y = NULL,
strip.switch.pad.grid = unit(0.1, "cm"),
strip.switch.pad.wrap = unit(0.1, "cm"),
plot.background = element_rect(color = NA),
plot.title = element_text(size = base_size * 1.8, hjust = 0.5,
vjust = 1, face = "bold",
margin = margin(b = half_line * 1.2)),
plot.subtitle = element_text(size = base_size * 1.3, hjust = 0.5, vjust = 1,
margin = margin(b = half_line * 0.9)),
plot.caption = element_text(size = rel(0.9), hjust = 1, vjust = 1,
margin = margin(t = half_line * 0.9)),
plot.tag = element_text(size = rel(1.2), hjust = 0.5, vjust = 0.5),
plot.tag.position = "topleft",
plot.margin = margin(base_size, base_size, base_size, base_size), complete = T)
}
浏览一下修改的外观,新的面板和网格线,还有坐标轴标度、文本和标题:
theme_set(theme_custom())
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() + labs(x = "Year", y = "Temperature (°F)") + guides(color = F)
这种改变绘图设计的方式值得大力推荐。因为它让你能快速一次性改变绘图的任何元素。 在数秒内让你的结果符合恰当的样式并满足其它任何需求(例如有更大字体大小用于演示或期刊需要)。
也可以通过theme_update()
快速进行设置:
theme_custom <- theme_update(panel.background = element_rect(fill = "gray60"))
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() + labs(x = "Year", y = "Temperature (°F)") + guides(color = F)
出于联系目的,我们用自己的主题,使用白色填充和不带有白色的小网格线:
theme_custom <- theme_update(panel.background = element_rect(fill = "white"),
panel.grid.major = element_line(size = 0.5),
panel.grid.minor = element_blank())
Working with Colors(颜色)
对于简单应用颜色在ggplot2
中是直接的,但是当你有更高级的需求时,可能会遇到挑战。对更高级的处理颜色的主题可以翻阅Hadley’s book ,这本书涵盖了很好的内容。也有几个其它的好资源包括 R Cookbook 和ggplot2
online docs。哥伦比亚的 Tian Zheng 创建了实用性的 PDF of R colors.
为了用你的数据使用颜色,对重要的是需要指导你是否正在处理分类或连续性的变量。
Categorical Variables: Manually Select Colors(分类变量:手动选择颜色)
(g <- ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
theme(legend.title = element_blank()) +
scale_color_manual(values = c("dodgerblue4", "darkolivegreen4",
"darkorchid3", "goldenrod1")))
Categorical Variables: Use Built-In Palettes(分类变量:使用内置的调色板)
可以用ColorBrewer palettes ,通过 scale_*_brewer
,这是ggplot2
包内置的函数:
g + scale_color_brewer(palette = "Set1")
可以忽略程序前台的信息,替换已有的标度为我们想要的。
Categorical Variables: Use Tableau colors(分类变量,使用Tableau颜色)
Tableau是著名的可视化软件,带有为人熟知的调色板。对R的用户,可以通过 ggthemes
的命令 scale_color_tableau()
获得:
library(ggthemes)
g + scale_color_tableau()
Continuous Variables: Default Color Schemes(连续性变量:默认的颜色方案)
本例中,我们要改变变量,把颜色赋予ozone,它是一个连续性的变量,同温度强相关(higher temperature = higher ozone)。函数scale_color_gradient()
是一个连续性的梯度,而scale_color_gradient2()
是另一个分支。
这是默认的ggplot2
连续颜色方案 (sequential color scheme):
ggplot(chic, aes(x = date, y = temp, color = o3)) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
scale_color_continuous("Ozone:")
此代码绘同样的图:
ggplot(chic, aes(x = date, y = temp, color = o3)) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
scale_color_gradient()
这里是另一个默认的颜色方案:
ggplot(chic, aes(x = date, y = temp, color = o3)) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
scale_color_gradient2()
Continuous Variables: Manually Set a Sequential Color Scheme(连续性变量:手动设置连续颜色方案)
梯度改变的颜色板被用于连续性变量,可以通过手动设置scale_*_gradient
:
ggplot(chic, aes(x = date, y = temp, color = o3)) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
scale_color_gradient(low = "darkkhaki", high = "darkgreen", "Ozone:")
温度数据是正态分布的,因此使用对比性大的颜色方案会怎样呢(不是连续性的颜色)。使用
scale_color_gradient2
函数用于diverging颜色:
mid <- max(chic$o3) / 2 # or mid <- mean(chic$o3)
ggplot(chic, aes(x = date, y = temp, color = o3)) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
scale_color_gradient2(midpoint = mid, low = "blue4",
mid = "white", high = "red4", "Ozone:")
Continuous Variables: The Beautiful Viridis Color Palette(连续性变量:美丽的翡翠调色板)
viridis color palettes 不仅是你的图形更漂亮和易于理解,还可以使色盲者易于阅读和以灰色的进行打印。你可以用 dichromate
测试在色盲适用的各种形式下你绘图是怎样的外观。
如下多面板的图形展示了4个翡翠调色板中的两个:
g <- ggplot(chic, aes(x = date, y = temp, color = o3)) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)")
library(viridis)
p1 <- g + scale_color_viridis("Ozone:") + ggtitle("'viridis' (default)")
p2 <- g + scale_color_viridis(option = "inferno", "Ozone:") + ggtitle("'inferno'")
p3 <- g + scale_color_viridis(option = "cividis", "Ozone:") + ggtitle("'cividis'")
library(patchwork)
(p1 + p2 + p3) * theme(legend.position = "bottom")
将翡翠调色板用于非连续的变量也是可能的。
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
theme(legend.title = element_blank()) +
scale_color_viridis(discrete = T, end = 1)
Working with Lines(线条)
Add Horizonal or Vertical Lines to a Plot(为图形添加水平或垂直的线)
你可能想强调给定的范围或阈值,使用geom_hline()
(对于水平线) 或者 geom_vline()
(用于垂直线),在给定的坐标位置绘制一条线 :
ggplot(chic, aes(x = date, y = temp, color = o3)) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
geom_hline(yintercept = c(0, 73))
如果你想非0或1位置添加一条斜线,需用用到'geom_abline()`。这里是一个例子,用于添加回归线。
reg <- lm(o3 ~ temp, data = chic)
ggplot(chic, aes(x = temp, y = o3)) +
geom_point(alpha = 0.5) +
labs(caption = paste0("y = ", round(coefficients(reg)[2], 2),
" * x + ", round(coefficients(reg)[1], 2)),
x = "Temperature (°F)", y = "Ozone") +
geom_abline(intercept = coefficients(reg)[1], slope = coefficients(reg)[2],
color = "darkorange2", size = 1.5)
随后,我们将学习怎样用命令添加线性拟合线,用`stat_smooth(method = "lm")。但是,可能有其它原因让我们添加一条给定斜率的的线。
Working with Text(文本)
Add Labels to Your Data(为你的数据添加标签)
有时,我们想为我们的数据点添加标签。为避免文本标签重叠或拥挤,使用1%原始数据抽样,均等代表四个季节。
set.seed(1)
library(tidyverse)
sample <- chic %>%
dplyr::group_by(season) %>%
dplyr::sample_frac(0.01)
## code without pipes:
## sample <- sample_frac(group_by(chic, season), 0.01)
chic %>%
group_by(season) %>%
sample_frac(0.01) %>%
ggplot(aes(x = date, y = temp, label = season)) +
geom_point() +
geom_text(aes(color = factor(temp)), hjust = 0.5, vjust = -0.5) +
labs(x = "Year", y = "Temperature (°F)") +
xlim(as.Date(c('1997-01-01', '2000-12-31'))) +
ylim(c(0, 90)) +
theme(legend.position = "none")
好吧,避免标签拥挤看起来不work。别担心,我们马上就解决。
可以用'geom_label '框图:
ggplot(sample, aes(x = date, y = temp, label = season)) +
geom_point() +
geom_label(aes(fill = factor(temp)), color = "white",
fontface = "bold", hjust = 0.5, vjust = -0.25) +
labs(x = "Year", y = "Temperature (°F)") +
xlim(as.Date(c('1997-01-01', '2000-12-31'))) +
ylim(c(0, 90)) +
theme(legend.position = "none")
很酷的一个包是
ggrepel
,它 为
ggplot2
提供了geoms以强制以上例子中重叠的标签分离。这里,我们展示了两者,原始的数据和我们带标签的抽样数据:
library(ggrepel)
ggplot(chic, aes(x = date, y = temp, label = season)) +
geom_point(alpha = 0.5) +
geom_point(data = sample, aes(color = factor(temp)), size = 2.5) +
geom_label_repel(data = sample, aes(fill = factor(temp)),
color = "white", fontface = "bold") +
labs(x = "Year", y = "Temperature (°F)") +
theme(legend.position = "none")
对于纯文本标签,使用 geom_text_repel
同样奏效。看一下所有的例子 usage examples.
Add Text Annotation in the Top-Right, Top-Left etc.(在上右边,上左等加入文本注释)
用 ggplot2
可以为 Inf
设置注释坐标,但是用处有限。这里是一个例子 (基于代码this Google group) 用grid
基于坐标标度来指定位置。0是最低,1是最高的位置。
grobTree
函数来自于 grid
包,可以创建网格图形对象,textGrob 创建文本图形对象。 annotation_custom()
函数来自于 ggplot2
,设计用grob作为输入。
library(grid)
my_grob <- grobTree(textGrob("This text stays in place!",
x = 0.1, y = 0.9, hjust = 0,
gp = gpar(col = "black",
fontsize = 15,
fontface = "bold")))
ggplot(chic, aes(x = temp, y = o3)) +
geom_point(color = "tan", alpha = 0.5) +
labs(x = "Temperature (°F)", y ="Ozone") +
annotation_custom(my_grob)
在你有很多图有不同的标度时,这个函数的作用尤其冥想。如下你看到的图中,坐标轴的范围有很大变化,上面同样的代码能用于在每个分图上同样的位置添加注释。
ggplot(chic, aes(x = temp, y = o3)) +
geom_point(color = "tan") +
labs(x = "Temperature (°F)", y ="Ozone") +
facet_wrap(~ season, scales = "free") +
annotation_custom(my_grob)
Working with Coordinates(标度)
Flip a Plot(翻转图像)
以图形的边翻转图像非常容易实现。在此我们引入coord_flip()
,需要它来翻转图像(顺便,我们用 geom_boxpot()
来绘制新的图形。
ggplot(chic, aes(x = season, y = o3)) +
geom_boxplot(fill = "indianred") +
labs(x = "Season", y = "Ozone") +
coord_flip()
Reverse an Axis(翻转坐标轴)
分别使用scale_x_reverse()
或scale_y_reverse()
很容易实现坐标轴翻转:
ggplot(chic, aes(x = date, y = temp, color = o3)) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
scale_y_reverse()
Transform an Axis(坐标轴转换)
… 使用scale_y_log10()
或scale_y_sqrt()
转换默认的线性绘图。例如,在此用 log10-转换坐标轴(注意,会引入NA):
ggplot(chic, aes(x = date, y = temp, color = o3)) +
geom_point() +
labs(x = "Year", y = "Temperature (°F)") +
scale_y_log10(lim = c(0.1, 100))
Circularize a Plot(环形绘图)
通过 coord_polar
让坐标系统成环形是可以滴(极性图)。
library(tidyverse)
chic %>%
dplyr::group_by(season) %>%
dplyr::summarize(o3 = median(o3)) %>%
ggplot(aes(x = season, y = o3)) +
geom_col(aes(fill = factor(season))) +
labs(x = "", y = "Median Ozone Level") +
coord_polar() +
guides(fill = F)
此坐标系统可以画饼图:
chic %>%
dplyr::mutate(o3_avg = median(o3)) %>%
dplyr::filter(o3 > o3_avg) %>%
dplyr::mutate(n_all = n()) %>%
dplyr::group_by(season) %>%
dplyr::summarize(rel = n() / unique(n_all)) %>%
ggplot(aes(x = "", y = rel)) +
geom_col(aes(fill = factor(season)), width = 1) +
labs(x = "",
y = "Proportion of Days Exceeding\nthe Median Ozone Level") +
coord_polar("y") +
scale_fill_brewer(palette = "Set1", name = "Season:") +
theme(axis.ticks = element_blank())
Working with Chart Types(图形)
Alternatives to a Box Plot(方框图的替代图)
方框图是很好的,但是可能特让人厌烦。有好几种替代的图形,但首先让我们画一个普通的方框图:
有效性? Yes.
趣味性? No.
1. Alternative: Plot of Points(替代图形:绘制点图)
让我们用原始数据绘制每个数据点:
g + geom_point(color = "firebrick")
不仅让人烦,而且没有提供有用的信息。为了改进图形,可以增加透明度来处理重叠点:
g + geom_point(color = "firebrick", alpha = 0.1)
然而,这里设了透明度也不行,因为重叠依然严重,高值或极值仍然不可见。糟糕了,来试试其它方法。
2. Alternative: Jitter the Points(替代图形:点的抖动)
试着为数据添加一些抖动。我超爱这个内部的可视化,但需要注意,人为添加的抖动增加了数据的噪音,可能导致数据的误导。
g + geom_jitter(aes(color = season), alpha = 0.25,
position = position_jitter(width = 0.3)) +
theme(legend.position = "none")
3. Alternative: Violin Plots(替代图形:小提琴图)
小提琴图通过方框图类似,其突出优势是用核密度来展示最多的数据,这是一种有益的可视化图形。
g + geom_violin(color = "sienna", fill = "red", alpha = 0.4)
4. Alternative: Combining Violin Plots with Jitter(替代图形:小提琴图和抖动合体)
当然可以组合使用两者,同时估计密度和有原始数据点:
g + geom_violin(aes(color = season), fill = "gray80", alpha = 0.5) +
geom_jitter(aes(color = season), alpha = 0.25,
position = position_jitter(width = 0.3)) +
theme(legend.position = "none") +
coord_flip()
ggforce
包 提供了所谓的sina 函数,抖动的宽度可以通过数据的密度来控制,可是让抖动图更具视觉吸引力:
library(ggforce)
g + geom_violin(aes(color = season), fill = "gray80", alpha = 0.5) +
geom_sina(aes(color = season), alpha = 0.25) +
theme(legend.position = "none") +
coord_flip()
5. Alternative: Combining Violin Plots with Box Plots(替代图形:小提琴图和框型图合体)
为了易于估计分位数,可以为小提琴图内部添加框型图,用于指示25%分位数、中位数和75%分位数:
g + geom_violin(aes(fill = season), color = "transparent", alpha = 0.5) +
geom_boxplot(outlier.alpha = 0, coef = 0,
color = "gray40", width = 0.1) +
theme(legend.position = "none") +
coord_flip()
Create a Rug Representation to a Plot(为图形添加地毯图形)
地毯表示单一定量变量的数据,表现形式是沿着坐标轴的标记。多数情况下,用于散点图或热图来展示一个或两个变量的整体分布:
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
geom_rug() +
labs(x = "Year", y = "Temperature (°F)") +
theme(legend.position = "none")
ggplot(chic, aes(x = date, y = temp, color = factor(season))) +
geom_point() +
geom_rug(sides = "r", alpha = 0.3) +
labs(x = "Year", y = "Temperature (°F)") +
theme(legend.position = "none")
Create a Tiled Correlation Plot(绘制瓦片相关图)
第一步是建立相关矩阵。我们用Pearson相关性,因为所有的变量都是相当的正态分布(但是可以用Spearman系数,如果变量遵循不同的分布模式) 。注意因为相关矩阵有冗余的信息,我们设置它的一半为 NA
。
corm <- round(cor(chic[ , sort(c("death", "temp", "dewpoint", "pm10", "o3"))],
method = "pearson", use = "pairwise.complete.obs"), 2)
corm[lower.tri(corm)] <- NA
corm
## death dewpoint o3 pm10 temp
## death 1 -0.47 -0.24 0.00 -0.49
## dewpoint NA 1.00 0.45 0.33 0.96
## o3 NA NA 1.00 0.21 0.53
## pm10 NA NA NA 1.00 0.37
## temp NA NA NA NA 1.00
现在我们用 reshape2
包的melt函数,把矩阵变为 long 形式,丢掉 NA
值的记录:
library(reshape2)
corm <- melt(corm)
corm$Var1 <- as.character(corm$Var1)
corm$Var2 <- as.character(corm$Var2)
corm <- na.omit(corm)
head(corm, 10)
## Var1 Var2 value
## 1 death death 1.00
## 6 death dewpoint -0.47
## 7 dewpoint dewpoint 1.00
## 11 death o3 -0.24
## 12 dewpoint o3 0.45
## 13 o3 o3 1.00
## 16 death pm10 0.00
## 17 dewpoint pm10 0.33
## 18 o3 pm10 0.21
## 19 pm10 pm10 1.00
画图我们用 geom_tile
,但是如你有很多数据,可以考虑用geom_raster
,它会更快。
ggplot(corm, aes(x = Var2, y = Var1)) +
geom_tile(data = corm, aes(fill = value), color = "white") +
labs(x = "Variable 2", y = "Variable 1") +
scale_fill_gradient2(low = "blue", high = "red", mid = "white",
midpoint = 0, limit = c(-1, 1),
name = "Correlation\n(Pearson)") +
theme(axis.text.x = element_text(angle = 45, size = 11,
vjust = 1, hjust = 1)) +
coord_equal()
Create a Contour Plot(画登高线图)
等高线图是展示三维数据的好方法,可以指明数值的末端阈值。在此,我们用露点数据画图(也就是 空气中的水蒸气凝结成液态录水的温度), 与温度和臭氧的浓度有关:
## interpolate data
library(akima)
fld <- with(chic, interp(x = temp, y = o3, z = dewpoint))
## prepare data in long format
library(reshape2)
df <- melt(fld$z, na.rm = T)
names(df) <- c("x", "y", "Dewpoint")
df$Temperature <- fld$x[df$x]
df$Ozone <- fld$y[df$y]
g <- ggplot(data = df, aes(x = Temperature, y = Ozone, z = Dewpoint)) +
theme(panel.background = element_rect(fill = "white"),
panel.border = element_rect(color = "black", fill = NA),
legend.title = element_text(size = 15),
axis.text = element_text(size = 12),
axis.title.x = element_text(size = 15, vjust = -0.5),
axis.title.y = element_text(size = 15, vjust = 0.2),
legend.text = element_text(size = 12))
g + stat_contour(aes(color = ..level.., fill = Dewpoint))
震惊了! 如其定义,露点多数情况下等于测量温度。
这些线表示的是不同的露点水平,但这不是一个靓图,由于缺少边界也难以阅读。让我们试着画一个瓦片图,用 viridis调色板编码露点的臭氧水平和温度组合:
g + geom_tile(aes(fill = Dewpoint)) +
scale_fill_viridis(option = "inferno")
让等高线图和瓦片图合体,在登高线下填充这些区域会怎样呢?
g + geom_tile(aes(fill = Dewpoint)) +
stat_contour(color = "white", size = 0.7, bins = 5) +
scale_fill_viridis()
Create a Joyplot aka Ridge Plot(一种波涛汹涌,哦不对,是山峰叠峦的可视化方式)
山峰叠峦Joyplots (亦称之为 屋脊(线)图)是一种新型的图形,此刻很流行。 (有趣的事实: 名字参考Joy Division’s “Unknown Pleasures” LP.封面)
你可以用 基本 ggplot
命令 绘图,此图的流行的后果就是有人写了一个包,更加容易绘制此类图形: ggridges
. 这里我们用一下这个包。
library(ggridges)
ggplot(chic, aes(x = temp, y = factor(year))) +
geom_density_ridges(fill = "gray90") +
labs(x = "Temperature (°F)", y = "Year")
使用参数 rel_min_height
和
scale`分别易于区分重叠和拖尾。这个包带有自己的主题(但是我更愿意自己造个轮子,见“Create and Use Your Custom Theme”)。另外,我们基于年度来变更颜色,使图形更具吸引力。
ggplot(chic, aes(x = temp, y = factor(year), fill = year)) +
geom_density_ridges(alpha = 0.8, color = "white",
scale = 2.5, rel_min_height = 0.01) +
labs(x = "Temperature (°F)", y = "Year") +
guides(fill = F) +
theme_ridges()
也能用scaling参数值小于1,来去除重叠(但是这个有悖于山峰叠峦的本意)。这是一个例子,用viridis
调色板:
ggplot(chic, aes(x = temp, y = season, fill = ..x..)) +
geom_density_ridges_gradient(scale = 0.9, gradient_lwd = 0.5,
color = "black") +
scale_fill_viridis(option = "plasma", name = "") +
labs(x = "Temperature (°F)", y = "Season:") +
theme_ridges(font_family = "Roboto Condensed", grid = F)
也可以比较每个山峰叠峦线的几个组,根据他们的组别来上色。这个剽窃了 Marc Belzunces的思路。
library(tidyverse)
## only plot extreme season using dplyr from the tidyverse
ggplot(data = filter(chic, season %in% c("Summer", "Winter")),
aes(x = temp, y = year, fill = paste(year, season))) +
geom_density_ridges(alpha = 0.7, rel_min_height = 0.01,
color = "white", from = -5, to = 95) +
scale_fill_cyclical(breaks = c("1997 Summer", "1997 Winter"),
labels = c(`1997 Summer` = "Summer",
`1997 Winter` = "Winter"),
values = c("tomato", "dodgerblue"),
name = "Season:", guide = "legend") +
theme_ridges(font_family = "Roboto Condensed") +
labs(x = "Temperature (°F)", y = "Year")
ggridges
包 在
geom_density_ridges
命令中用
stat = "binline"
创建直方图是有用的:
ggplot(chic, aes(x = temp, y = factor(year), fill = year)) +
geom_density_ridges(stat = "binline", bins = 25, scale = 0.9,
draw_baseline = F, show.legend = F) +
theme_ridges(font_family = "Roboto Condensed") +
labs(x = "Temperature (°F)", y = "Season")
Working with Ribbons (AUC, CI, etc.)(丝带图)
展示丝带图的数据不是非常理想,但是丝带图非常有用。此例中,我们将用filter()
函数绘制一个30天的动态平均,以便让我们的丝带的噪音不会太多。
chic$o3run <- as.numeric(stats::filter(chic$o3, rep(1/30, 30), sides = 2))
ggplot(chic, aes(x = date, y = o3run)) +
geom_line(color = "chocolate", lwd = 0.8) +
labs(x = "Year", y = "Temperature (°F)")
如果我们用geom_ribbon()
函数为曲线下的区域添充,看起来会如何呢?
ggplot(chic, aes(x = date, y = o3run)) +
geom_ribbon(aes(ymin = 0, ymax = o3run), fill = "orange",
color = "orange", alpha = 0.4) +
geom_line(color = "chocolate", lwd = 0.8) +
labs(x = "Year", y = "Temperature (°F)")
很好表明了曲线下面积 area under the curve (AUC),但是这不是 geom_ribbon()
的经典实用方式。替代方法是,我们绘制一条丝带,在我们数据的上下添加标准差:
chic$mino3 <- chic$o3run - sd(chic$o3run, na.rm = T)
chic$maxo3 <- chic$o3run + sd(chic$o3run, na.rm = T)
ggplot(chic, aes(x = date, y = o3run)) +
geom_ribbon(aes(ymin = mino3, ymax = maxo3), alpha = 0.5,
fill = "darkseagreen3", color = "transparent") +
geom_line(color = "aquamarine4", lwd = 0.7) +
labs(x = "Year", y = "Temperature (°F)")
Working with Smoothings(平滑线)
实用ggplot2为数据添加平滑线易如反掌。
Default: Adding a LOESS or GAM Smoothing(默认方式:添加LOESS或GAM平滑线)
简单实用stat_smooth()
– 甚至都不用公式。如果数据少于1000个点,这个添加了LOESS 线(局部权重的散点平滑线,method = "loess") 或者 GAM线 (广义加法模型, method = "gam") 。由于我们点多于1000个,平滑线基于GAM。
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "gray40", alpha = 0.5)+
labs(x = "Year", y = "Temperature (°F)") +
stat_smooth()
Specifying the Formula for Smoothing(为平滑线定义公式)
ggplot2
让你可以想用的方式定义模型。比如增加GAM的维度(为平滑线加入一些其他额外的起伏):
ggplot(chic, aes(x = date, y = temp)) +
geom_point(color = "gray40", alpha = 0.3) +
labs(x = "Year", y = "Temperature (°F)") +
stat_smooth(method = "gam", formula = y ~ s(x, k = 1000),
se = F, size = 1.3, aes(col = "1000")) +
stat_smooth(method = "gam", formula = y ~ s(x, k = 100),
se = F, size = 1, aes(col = "100")) +
stat_smooth(method = "gam", formula = y ~ s(x, k = 10),
se = F, size = 0.8, aes(col = "10")) +
scale_color_manual(name = "k", values = c("darkorange2",
"firebrick",
"dodgerblue3"))
Adding a Linear Fit(加入线性拟合)
虽然默认的是 LOESS或GAM平滑线,添加标准的线性拟合也相当容易 :
ggplot(chic, aes(x = temp, y = death)) +
geom_point(color = "gray40", alpha = 0.5) +
labs(x = "Temperature (°F)", y = "Deaths") +
stat_smooth(method = "lm", col = "firebrick", se = F, size = 1.3)
Working with Interactive Plots(交互绘图)
Shiny
Shiny是RStudio的一个包,使得用R创建交互网络应用非常便捷,介绍和实例,见 Shiny homepage.
浏览一下潜在用途,可以看Hello Shiny例子。这是第一个:
Plot.ly
Plot.ly 可以用你的ggplot2
很容易创建在线的交互图形。过程相当容易,用R就可以实现。
Remarks, Tipps & Tricks(备注、提示和技巧)
Using ggplot2
in Loops and Functions(在循环和函数中用ggplot2)
基于网格的图形函数lattice和ggplot2中创建图形对象。 当你在命令行交互使用这些函数时,结果就会自动打印,但是在 source()
或你自己的函数中,需要明确声明print()
, i.e. 在我们的例子中的print(g)
。也见 Q&A page of R.
其它资源
- “Fundamentals of Data Visualization”, an online book by Claus Wilke about data visualization in general but using
ggplot2
. (You can find the codes on his GitHub profile.) - “Cookbook for R”, an online and printed book by Winston Chang with reciped to quickly produce the desired plot.