R 数据可视化 —— ggforce(注释和分面)

接上一节内容,这一节主要介绍 ggforce 提供的分组注释以及分面功能

3. 分组注释

ggforce 提供了一个很方便的分组注释功能。例如,我们想展示不同种类的鸢尾花在花瓣长度和宽度上的区别,使用 ggplot2,我们常用的绘制方式是

p <- ggplot(iris, aes(Petal.Length, Petal.Width, colour = Species)) +
  geom_point(show.legend = FALSE)
p

不同种类用颜色来标注

使用 ggforce 可以为不同种类的点添加区域和文本注释,可以更容易的从图中分辨不同类别的点。主要包含 4 种不同形状的注释:

  • geom_mark_circle()
  • geom_mark_ellipse()
  • geom_mark_hull()
  • geom_mark_rect()

除了形状不同之外,其他都一样。

下面,我们来添加矩形注释

p + geom_mark_rect() 

只需添加一个函数,而不用做其他任何操作,就能为每个分组的点添加一个矩形框,简单快捷。

想要添加标签和箭头,也非常方便,直接设置 label 参数即可

p + geom_mark_rect(aes(label = Species))

标签和箭头的位置会自动优化调整,并不需要我们指定。

添加椭圆注释

p + geom_mark_ellipse(aes(label = Species))

圆形

p + geom_mark_circle(aes(label = Species))

添加不同的主题

p + geom_mark_rect(aes(label = Species), show.legend = FALSE) +
  theme_void()

但是,在有些情况下,使用矩形或者圆形注释并不好,或者说不够理想。这时就可以使用 geom_mark_hull 函数,来绘制更加复杂的多边形边界,随着分组的边界绘制线条

使用前,先安装依赖包 concaveman

install.packages("concaveman")

更换注释函数

p + geom_mark_hull(aes(label = Species)) +
  theme_void() 

这样的结果已经很不错了,还可以为每个分组区域添加填充色

p + 
  geom_mark_hull(aes(label = Species, fill = Species), show.legend = FALSE) +
  theme_void() 

ggforce 会自动为填充色添加透明度,以防分组的重叠区域被覆盖,也可以手动设置 alpha 参数,来调整透明度

另一个对 hull 函数比较重要的参数就是这是整个区域的大小,就是更改区域周围 padding 的大小。对应的参数是 expand,可以使用 unit 来指定大小

p + 
  geom_mark_hull(
    aes(label = Species, fill = Species), 
    show.legend = FALSE, expand = unit(3, "mm")) +
  theme_void() 

可以看到,区域边界更加紧密了

4. 分面

ggplot2 所提供的分面函数:facet_gridfacet_wrap,基本上可以满足大部分的需求。ggforce 扩展了分面的功能,能够适用于任何布局

4.1 分页

当变量过多时,facet_wrap()facet_grid() 生成的图片中,每个面板都被压缩得很小,例如

ggplot(diamonds) +
  geom_point(aes(carat, price), alpha = 0.1) +
  facet_wrap(~cut:clarity, ncol = 3)

ggforce 为这两个函数提供了一个分页版本,通过设置每一页的行列数,以及页数,可以对变量分页进行绘制,例如

ggplot(diamonds) +
  geom_point(aes(carat, price), alpha = 0.1) +
  facet_wrap_paginate(~cut:clarity, ncol = 3, nrow = 3, page = 2)

每页包含 33 列,绘制的是第二页。

对于 facet_grid 也是一样的

ggplot(diamonds) +
  geom_point(aes(carat, price), alpha = 0.1) +
  facet_grid_paginate(color~cut:clarity, ncol = 3, nrow = 3, page = 4)

可以使用 n_pages 来获取页数

> p <- ggplot(diamonds) +
  geom_point(aes(carat, price), alpha = 0.1) +
  facet_wrap_paginate(~cut:clarity, ncol = 3, nrow = 3, page = 1)

> n_pages(p)
[1] 5

4.2 内容缩放

ggplot2 的缩放包括:坐标系统的缩放和位置的缩放,而 ggforce 提供了一个更强大的函数:facet_zoom

例如,放大 versicolor 类的 x 轴对应的区域

ggplot(iris, aes(Petal.Length, Petal.Width, colour = Species)) +
    geom_point() +
    facet_zoom(x = Species == "versicolor")

或者 y 坐标轴对应的区域

ggplot(iris, aes(Petal.Length, Petal.Width, colour = Species)) +
  geom_point() +
  facet_zoom(y = Species == "versicolor")

或者,指定 xy 共同的区域

ggplot(iris, aes(Petal.Length, Petal.Width, colour = Species)) +
  geom_point() +
  facet_zoom(xy = Species == "versicolor")

为不同的轴指定不同的条件

ggplot(iris, aes(Petal.Length, Petal.Width, colour = Species)) +
    geom_point() +
    facet_zoom(x = Species != 'setosa', y = Species == 'versicolor')

还可以将每个轴的范围分开绘制

ggplot(iris, aes(Petal.Length, Petal.Width, colour = Species)) +
    geom_point() +
    facet_zoom(x = Species != 'setosa', y = Species == 'versicolor', 
               split = TRUE)

使用 xlimylim 来确定范围

ggplot(iris, aes(Petal.Length, Petal.Width, colour = Species)) +
  geom_point() +
  facet_zoom(xlim = c(4, 5), ylim = c(1, 2), 
             split = TRUE)

设置区域的颜色

ggplot(iris, aes(Petal.Length, Petal.Width, colour = Species)) +
  geom_point() +
  facet_zoom(xlim = c(4, 5), ylim = c(1, 2), 
             split = TRUE) +
  theme(zoom = element_rect(fill = 'orange', colour = NA), validate = FALSE)

与注释一起使用

ggplot(iris, aes(Petal.Length, Petal.Width, colour = Species)) +
  geom_point(show.legend = FALSE) + 
  geom_mark_hull(
    aes(label = Species, fill = Species), 
    show.legend = FALSE, expand = unit(3, "mm")) +
  theme_no_axes() +
  facet_zoom(x = Species == "versicolor")

5. 标度

我们的数据一般都会带有相应的单位,比如身高 cm,体重 kg 等,但是我们在分析的时候一般会忽略数值的单位,而 ggforce 可以让我们在绘图时,加上数值单位

这一功能有 units 包提供

library(units)

定义单位

miles <- as_units('miles')
gallon <- as_units('gallon')
horsepower <- as_units('horsepower')

为数据添加单位,直接与单位相乘即可

> mtcars$consumption <- mtcars$mpg * (miles/gallon)
> mtcars$power <- mtcars$hp * horsepower

> head(mtcars$power)
Units: [horsepower]
[1] 110 110  93 110 175 105

绘制图形

ggplot(mtcars) +
  geom_point(aes(power, consumption, colour = factor(cyl)))

aes 中的变换会直接反映到图中

ggplot(mtcars) +
  geom_point(aes(power, 1/consumption, colour = factor(cyl)))

也可以使用 scale* 函数,设置 unit 参数,会自动变换为新的单位

ggplot(mtcars) +
  geom_point(aes(power, consumption, colour = factor(cyl))) +
  scale_x_unit(unit = 'W') +
  scale_y_unit(unit = 'km/l')

6. 变换

ggplot2 的变换其实使用的是 scales 包,而不是其自身的一部分。ggforce 扩展了 ggplot 的变换功能,包括对坐标轴的变换

6.1 单变量变换

这些变换主要针对 scales 包缺少的功能,如

幂变换
> p3 <- power_trans(3)
> p3$transform(1:5)
[1]   1   8  27  64 125
ggplot(mtcars) + geom_point(aes(mpg, cyl)) + scale_y_continuous(trans = p3)
逆变换

scales 包提供了逆线性变换,但是没有提供其他函数的逆变换,比例 log 的逆变换。

> p3r <- trans_reverser(p3)
> p3r
Transformer:  reverse-power of 3
> p3r$transform(1:5)
[1]   -1   -8  -27  -64 -125
ggplot(mtcars) + geom_point(aes(mpg, cyl)) + scale_y_continuous(trans = p3r)

6.2 坐标变换

径向变换

radial_trans 可以将半径和角度转换为笛卡尔坐标系下的 xy 轴坐标

line <- data.frame(
  x = seq(0, 10, length.out = 100), 
  y = seq(0, 10, length.out = 100)
)
r_trans <- radial_trans(r.range = c(0, 1), a.range = c(0, 2))
spiral <- r_trans$transform(r = line$x, a = line$y)
ggplot() + geom_path(aes(x, y), data = line, colour = 'red') + 
  geom_path(aes(x, y), data = spiral, colour = 'blue')

线性变换

线性变换系列涵盖了缩放/拉伸、旋转、剪切、反射和平移,所有的变换都是相对于原始位置进行的。

# 定义旋转、剪切和坐标平移
trans <- linear_trans(rotate(a), shear(1, 0), translate(x1, y1))
square <- data.frame(x = c(0, 0, 1, 1), y = c(0, 1, 1, 0))
# 旋转 60,x + 4, y + 8
square2 <- trans$transform(square$x, square$y, a = pi/3, x1 = 4, y1 = 8)
# 旋转 60,x + 2, y - 6
square3 <- trans$transform(square$x, square$y, a = pi/1.5, x1 = 2, y1 = -6)
square_all <- rbind(square, square2, square3)
square_all$group <- rep(1:3, each = 4)
ggplot(square_all, aes(x, y, group = group)) +
    geom_polygon(aes(fill = factor(group)), colour = 'black')

你可能感兴趣的:(R 数据可视化 —— ggforce(注释和分面))