Code
library(plot3D)
# 设定主标题,图例标题, 设定标度断点以着色, 默认scale = TRUE表示3个坐标轴独立缩放
persp3D(
z = volcano,
scale = TRUE,
main = "volcano",
clab = c("height(m)"),
breaks = seq(100, 200, by = 10), # 设置颜色标度断点
)
Rui
September 15, 2022
plot3D
plot3D
程序包可用于用于可视化 2D 和 3D 数据,包括透视图、切片图、曲面图、散点图等。其中不少函数都是基于 base
中的 persp
和 image
编写的,可以认为是基础绘图函数的拓展。
plot3D
包含很多函数,其中基于 persp
函数的有:
persp3D
: 基础包中 persp
函数的拓展
ribbon3D
:绘制带状透视图
hist3D
:绘制 3D 直方图
scatter3D
, points3D
, lines3D
:绘制着色的 3D 散点图、点图、曲线图
其他
基于 image
函数的有:
image2D
:使用平面图像可视乎 2D 或 3D 数据
其他
还有其他函数在这里不一一列出。本文主要围绕核心函数 persp3D
来展示 2 维函数的可视化方法。
persp3D
参数介绍persp3D
函数的使用方法如下:
persp3D(x = seq(0, 1, length.out = nrow(z)),
y = seq(0, 1, length.out = ncol(z)), z,
...,
colvar = z, phi = 40, theta = 40,
col = NULL, NAcol = "white", breaks = NULL,
border = NA, facets = TRUE, colkey = NULL, resfac = 1
image = FALSE, contour = FALSE, panel.first = NULL,
clim = NULL, clab = NULL, bty = "b",
lighting = FALSE, shade = NA, ltheta = -135, lphi = 0,
inttype = 1, curtain = FALSE, add = FALSE, plot = TRUE)
参数实在太多,挑几个重要并且常用的讲一讲:
x
,y
:x 轴、y 轴取值,是一个向量
z
:z 轴取值,为一个 2 维矩阵。相当于记录了每一对 (x,y) 所对应的函数值。所以要注意:x 长度(length(x)
)要等于 z 的行数(nrow(z)
),y 的长度(length(y)
)要等于 z 的列数(ncol(z)
)。
colvar
:用于着色的变量。如果给定,则它的维度应该与 z
的维度相同。若输入 NULL,NA 或 FALSE 将根据 colvar
切换颜色,仅当 boder
参数被指定颜色,shade > 0
,或 lighting = TRUE
才会产生好的效果。
col
:用于 colvar
变量的调色板。 如果 col = NULL
并且 colvar
被 指定,将使用红-黄-蓝配色方案。如果 col =NULL
并且 colvar
没有被指定,那么 col
将为灰色。为了与 persp
函数一致,设定 colvar = NULL
时 col
为一个矩阵,其维度为 nrow(z)-1
行,ncol(z)-1
列。
NAcol
:表示指定 colvar
中缺失值的颜色,默认值为 white。
breaks
:为一有限向量用来表示 colvar
的断点,必须比 colvar
多一个断点并且按升序排列,无序向量会被自动排序。
colkey
:为布尔值或 NULL (默认值)或参数列表(列表中包含的参数相当多,这里不再展开),用来指定图例参数。实际上 plot3D
中还存在一个 colkey()
的函数,其参数与传入 colkey
的参数列表相同。
add
:为布尔值,表示是否将该绘图对象添加到现有的绘图对象中,默认 FALSE 新建图层,TRUE 则添加图层。
plot
:为布尔值,表示是否绘图,默认 TRUE
则绘图,FALSE
则返回视角转换矩阵。
clab
:表示指定图例标题内容。只有当 colkey = TRUE
时,标签才会写在 colkey
的顶部。 标签将写在与主标题相同的水平线上。 为了避免这种情况,可以设置 clab
为一个向量,第一个值为空字符串,以此来降低标签的水平位置。
clim
:表示指定图例显示范围,当 colvar
被指定时生效,若 clim
范围超出 colvar
则超出部分显示为 NA。
theta
,phi
:指定观察透视图的方向,与 persp()
中一致。
border
:指定曲面网格边线的颜色,默认值为 NA 不显示曲面网格边线。
facets
:布尔值或 NA,表示是否指定曲面网格的颜色,TRUE 则用 col
参数指定曲面网格的颜色,FALSE 则为网格为颜色为白色且网格边线为 col
指定的颜色(前提是 border = NA
)。
image
:为布尔值,表示是否在绘图立方体插入另一个平面图, 如果设置为 TRUE,则会在 3D 图底部绘制图像,还允许传递 image2D()
函数的参数的列表,
此列表的一个参数 side
表示将 image2D()
图置于何处位置。 side = z-value
,表示将该图置于 z 轴 value 值位置处。 side = "zmin"
,side = "zmax"
分别将该图置于底部和顶部,默认置于底部。
contour
:为布尔值,表示是否在绘图立方体中插入等高线, 如果设定为 TRUE, 则默认在 3D 图底部插入等高线图(也是一个平面图),也可以通过 contour()
函数传递参数。 同样存在位置参数side
, side = "zmin"
, side = "zmax"
分别将该图置于底部和顶部,默认置于底部。
其他参数将在下一节示例中演示
也可以不指定颜色断点:
volcano 为该包中自带的数据集,这里省略了 x 和 y 的取值范围。scale
接受一个布尔值用于缩放坐标轴比例,TRUE (默认值)代表 3 个坐标轴各自独立缩放(不等比例缩放)
没有指定调色板 col
,所以默认使用红黄蓝配色。
其中,expand
参数用于缩放 z 轴,expand
< 1 则缩小 z 轴。
在描述 clab
参数时可能没太明白什么意思,其实根据上图就很好理解:图的主标题“volcano”应该位于整个图的最高点,而图例的标题与主标题位于同一水平线上显然不太合理。于是可以设置 clab
为一个向量,并且第一个元素为一个空字符串,如此可以降低图例标题的高度:
但可以看出效果不太理想。使用 manual 中的另一种方法:通过设置 colkey
传入的参数列表中的 line.clab
来降低图例标题的高度。
效果还是不理想,line.clab
只降低了图例标题的高度却导致与图例重合。多次尝试后选择设置 shift
参数来同时调整图例标题与图例的高度。
效果很好!同时设置 dist
参数来调节主图与图例的距离,dist
为负数则使图例靠近主图,为正数则远离主图,建议范围为 [-0.5, 0.05]。
除此之外还可以通过 side
设置图例放置的位置, 1 = bottom, 2 = left, 3 = top, 4 = right。length
调整图例长度。
使用 contour
添加等高线图,contour
也接受一个参数向量,参数向量同函数 contour2D
接受的参数一致。
zlim
用来指定 z 轴的坐标范围。既然要插入平面图,那么就应该手动调整 z 轴范围为图像留有足够空间。
设置 contour = TRUE
仅仅是使用绘制等高线的默认设置,可以看出默认设置下等高线为黑色且等高线平面位于 3D 图像的底部。若要画出精致的图像则需要进一步设置。
设置 nlevels
来指定等高线数量,col
设置等高线颜色。
使用 image
添加平面图像,image
也接受一个参数向量,参数向量同函数 image2D
接受的参数一致。
通过 col
设置平面图像的背景色。
还可以联合使用等高线图与平面图,只需要让等高线图与平面图位于同一 z 轴高度(默认设置下就可以):
还可以通过设置不同的水平高度将等高线图与平面图分离开:
关于 ribbon3D
和 hist3D
不再具体说明。
为了方便展示,这里使用二元 Rastrigin 函数,区间范围设置为 [-5, 5]:
\[ f(X)=\sum_{i=1}^{2}(x_i^2-10\cos(2\pi x_i)+10) \]
平面图像:
---
title: "使用 plot3D 画三维图"
author: "Rui"
date: "2022-09-15"
categories: [R, 可视化, plot3D]
image: "jellyfish.jpg"
format:
html:
code-fold: true
code-tools: true
---
```{r setup, include = FALSE}
# 设置默认参数
knitr::opts_chunk$set(
echo = TRUE,
fig.align = "center",
message = FALSE,
warning = FALSE,
collapse = TRUE
)
```
## 初识 `plot3D`
`plot3D` 程序包可用于用于可视化 2D 和 3D 数据,包括透视图、切片图、曲面图、散点图等。其中不少函数都是基于 `base` 中的 `persp` 和 `image` 编写的,可以认为是基础绘图函数的拓展。
::: callout-note
除此之外还有很多其他可以实现 3D 数据可视化的软件包(可能更适合你的工作),如:`rgl`,`scatterplot3D`,`misc3D` 等。这些包以及对应的使用说明(manual)都可以在 [CRAN](https://cran.r-project.org/) 上搜索到。
:::
`plot3D` 包含很多函数,其中基于 `persp` 函数的有:
- `persp3D`: 基础包中 `persp` 函数的拓展
- `ribbon3D`:绘制带状透视图
- `hist3D`:绘制 3D 直方图
- `scatter3D`, `points3D`, `lines3D`:绘制着色的 3D 散点图、点图、曲线图
- 其他
基于 `image` 函数的有:
- `image2D`:使用平面图像可视乎 2D 或 3D 数据
- 其他
还有其他函数在这里不一一列出。本文主要围绕核心函数 `persp3D` 来展示 2 维函数的可视化方法。
## `persp3D` 参数介绍
`persp3D` 函数的使用方法如下:
```
persp3D(x = seq(0, 1, length.out = nrow(z)),
y = seq(0, 1, length.out = ncol(z)), z,
...,
colvar = z, phi = 40, theta = 40,
col = NULL, NAcol = "white", breaks = NULL,
border = NA, facets = TRUE, colkey = NULL, resfac = 1
image = FALSE, contour = FALSE, panel.first = NULL,
clim = NULL, clab = NULL, bty = "b",
lighting = FALSE, shade = NA, ltheta = -135, lphi = 0,
inttype = 1, curtain = FALSE, add = FALSE, plot = TRUE)
```
参数实在太多,挑几个重要并且常用的讲一讲:
- `x`,`y`:x 轴、y 轴取值,是一个向量
- `z`:z 轴取值,为一个 2 维矩阵。相当于记录了每一对 (x,y) 所对应的函数值。所以要注意:x 长度(`length(x)`)要等于 z 的行数(`nrow(z)`),y 的长度(`length(y)`)要等于 z 的列数(`ncol(z)`)。
- `colvar`:用于着色的变量。如果给定,则它的维度应该与 `z` 的维度相同。若输入 NULL,NA 或 FALSE 将根据 `colvar` 切换颜色,仅当 `boder` 参数被指定颜色,`shade > 0`,或 `lighting = TRUE`才会产生好的效果。
- `col`:用于 `colvar` 变量的调色板。 如果 `col = NULL` 并且 `colvar` 被
指定,将使用红-黄-蓝配色方案。如果 `col =NULL` 并且 `colvar` 没有被指定,那么 `col` 将为灰色。为了与 `persp` 函数一致,设定 `colvar = NULL`时 `col` 为一个矩阵,其维度为 `nrow(z)-1` 行,`ncol(z)-1` 列。
- `NAcol`:表示指定 `colvar` 中缺失值的颜色,默认值为 white。
- `breaks`:为一有限向量用来表示 `colvar` 的断点,必须比 `colvar` 多一个断点并且按升序排列,无序向量会被自动排序。
- `colkey`:为布尔值或 NULL (默认值)或参数列表(列表中包含的参数相当多,这里不再展开),用来指定图例参数。实际上 `plot3D` 中还存在一个 `colkey()` 的函数,其参数与传入 `colkey` 的参数列表相同。
- `add`:为布尔值,表示是否将该绘图对象添加到现有的绘图对象中,默认 FALSE 新建图层,TRUE 则添加图层。
- `plot`:为布尔值,表示是否绘图,默认 `TRUE` 则绘图,`FALSE` 则返回视角转换矩阵。
- `clab`:表示指定图例标题内容。只有当 `colkey = TRUE` 时,标签才会写在 `colkey` 的顶部。 标签将写在与主标题相同的水平线上。 为了避免这种情况,可以设置 `clab` 为一个向量,第一个值为空字符串,以此来降低标签的水平位置。
- `clim`:表示指定图例显示范围,当 `colvar` 被指定时生效,若 `clim` 范围超出 `colvar` 则超出部分显示为 NA。
- `theta`,`phi`:指定观察透视图的方向,与 `persp()` 中一致。
- `border`:指定曲面网格边线的颜色,默认值为 NA 不显示曲面网格边线。
- `facets`:布尔值或 NA,表示是否指定曲面网格的颜色,TRUE 则用 `col` 参数指定曲面网格的颜色,FALSE 则为网格为颜色为白色且网格边线为 `col` 指定的颜色(前提是 `border = NA`)。
- `image`:为布尔值,表示是否在绘图立方体插入另一个平面图,
如果设置为 TRUE,则会在 3D 图底部绘制图像,还允许传递 `image2D()` 函数的参数的列表,此列表的一个参数 `side` 表示将 `image2D()` 图置于何处位置。
`side = z-value`,表示将该图置于 z 轴 value 值位置处。
`side = "zmin"`,`side = "zmax"` 分别将该图置于底部和顶部,默认置于底部。
- `contour`:为布尔值,表示是否在绘图立方体中插入等高线, 如果设定为 TRUE, 则默认在 3D 图底部插入等高线图(也是一个平面图),也可以通过 `contour()` 函数传递参数。同样存在位置参数`side`, `side = "zmin"`, `side = "zmax"` 分别将该图置于底部和顶部,默认置于底部。
- 其他参数将在下一节示例中演示
::: callout-note
`ribbon3D` 和 `hist3D` 的参数传导类似,不再具体说明
:::
## 动手绘制 3D 图
### Example 1
```{r}
library(plot3D)
# 设定主标题,图例标题, 设定标度断点以着色, 默认scale = TRUE表示3个坐标轴独立缩放
persp3D(
z = volcano,
scale = TRUE,
main = "volcano",
clab = c("height(m)"),
breaks = seq(100, 200, by = 10), # 设置颜色标度断点
)
```
也可以不指定颜色断点:
```{r}
persp3D(
z = volcano,
x = 1: nrow(volcano),
y = 1:ncol(volcano),
expand = 0.5,
main = "volcano",
scale = FALSE,
clab = "height(m)"
)
```
volcano 为该包中自带的数据集,这里省略了 x 和 y 的取值范围。`scale` 接受一个布尔值用于缩放坐标轴比例,TRUE (默认值)代表 3 个坐标轴各自独立缩放(不等比例缩放)。
没有指定调色板 `col`,所以默认使用红黄蓝配色。
其中,`expand` 参数用于缩放 z 轴,`expand` < 1 则缩小 z 轴。
### Example 2
在描述 `clab` 参数时可能没太明白什么意思,其实根据上图就很好理解:图的主标题“volcano”应该位于整个图的最高点,而图例的标题与主标题位于同一水平线上显然不太合理。于是可以设置 `clab` 为一个向量,并且第一个元素为一个空字符串,如此可以降低图例标题的高度:
```{r}
persp3D(
z = volcano,
scale = TRUE,
main = "volcano",
clab = c(" ", "height(m)"),
)
```
但可以看出效果不太理想。使用 manual 中的另一种方法:通过设置 `colkey` 传入的参数列表中的 `line.clab` 来降低图例标题的高度。
```{r}
persp3D(
z = volcano,
scale = TRUE,
main = "volcano",
colkey = list(line.clab=-0.5),
clab = c("height(m)"),
)
```
效果还是不理想,`line.clab` 只降低了图例标题的高度却导致与图例重合。多次尝试后选择设置 `shift` 参数来同时调整图例标题与图例的高度。
```{r}
persp3D(
z = volcano,
scale = TRUE,
main = "volcano",
colkey = list(shift=-0.05, dist=-0.1),
clab = c("height(m)"),
)
```
效果很好!同时设置 `dist` 参数来调节主图与图例的距离,`dist` 为负数则使图例靠近主图,为正数则远离主图,建议范围为 [-0.5, 0.05]。
除此之外还可以通过 `side` 设置图例放置的位置, **1 = bottom, 2 = left, 3 = top, 4 = right**。`length` 调整图例长度。
```{r}
persp3D(
z = volcano,
scale = TRUE,
expand = 0.5,
main = "volcano",
colkey = list(side = 1, length = 0.5),
clab = c("height(m)"),
facets = FALSE,
)
```
### Example 3
使用 `contour` 添加等高线图,`contour` 也接受一个参数向量,参数向量同函数 `contour2D` 接受的参数一致。
```{r}
x <- seq(1, nrow(volcano), by = 3)
y <- seq(1, ncol(volcano), by = 3)
Volcano <- volcano[x, y]
persp3D(z = Volcano, contour = TRUE, zlim= c(-200, 200), image = FALSE)
```
`zlim` 用来指定 z 轴的坐标范围。既然要插入平面图,那么就应该手动调整 z 轴范围为图像留有足够空间。
设置 `contour = TRUE` 仅仅是使用绘制等高线的默认设置,可以看出默认设置下等高线为黑色且等高线平面位于 3D 图像的底部。若要画出精致的图像则需要进一步设置。
设置 `nlevels` 来指定等高线数量,`col` 设置等高线颜色。
```{r}
persp3D(
z = Volcano, x = x, y = y,
scale = FALSE,
contour = list(nlevels = 20, col = "red"),
zlim = c(-200, 200),
expand = 0.2
)
```
### Example 4
使用 `image` 添加平面图像,`image` 也接受一个参数向量,参数向量同函数 `image2D` 接受的参数一致。
```{r}
persp3D(z = Volcano, zlim = c(-200, 200), image = TRUE)
```
通过 `col` 设置平面图像的背景色。
```{r}
persp3D(
z = Volcano, x = x, y = y,
scale = FALSE,
zlim = c(-200, 200),
expand = 0.2,
image = list(col = grey(seq(0, 1, length.out = 100)))
)
```
还可以联合使用等高线图与平面图,只需要让等高线图与平面图位于同一 z 轴高度(默认设置下就可以):
```{r}
persp3D(
z = Volcano, x = x, y = y,
scale = FALSE,
contour = list(nlevels = 20, col = "red"),
zlim = c(-200, 200),
expand = 0.2,
image = list(col = grey (seq(0, 1, length.out = 100)))
)
```
还可以通过设置不同的水平高度将等高线图与平面图分离开:
```{r}
persp3D(
z = Volcano,
contour = list(side = c("zmin", "z", "350")),
zlim = c(-100, 400),
phi = 20,
image = list(side = 350)
)
```
### Example 5
关于 `ribbon3D` 和 `hist3D` 不再具体说明。
```{r}
ribbon3D(z = Volcano, contour = TRUE, zlim= c(-100, 200), image = TRUE)
```
```{r}
VV <- volcano[seq(1, 87, 10), seq(1, 61, 10)]
hist3D(z = VV, scale = FALSE, expand = 0.01, border = "black")
```
## Rastrigin 函数
为了方便展示,这里使用二元 Rastrigin 函数,区间范围设置为 [-5, 5]:
$$
f(X)=\sum_{i=1}^{2}(x_i^2-10\cos(2\pi x_i)+10)
$$
```{r}
a <- 5
x <- y <- seq(-a, a, 0.05)
f <- function(x, y){
x^2 - 10*cos(2*pi*x) + y^2 - 10*cos(2*pi*y) + 20
}
z <- outer(x, y, f)
```
平面图像:
```{r}
image(x, y, z, col = heat.colors(24))
```
```{r}
library(plot3D)
persp3D(
z = z,
x = x,
y = y,
zlim = c(-20, 90),
main = "Rastrigin",
scale = FALSE,
expand = 0.1,
clab = "value",
colkey = list(shift=-0.05, dist=-0.1, length = 0.8),
image = list(col = grey (seq(0, 1, length.out = 100))),
phi = 30
)
```