ggplot2坐标轴的百分比转换

当绘制的变量是以百分比为单位时,最好的办法就是为坐标轴标签添加百分号(%). 这样可以在处理百分比的数据时使得数据的可视化更加清晰明了。

下面我们使用一个示例数据集来说明这一点。

library(dplyr)
data(mtcars)

cyl <- mtcars %>%
  count(cyl) %>%
  mutate(pct = n / sum(n) * 100) %>%
  print()
##   cyl  n    pct
## 1   4 11 34.375
## 2   6  7 21.875
## 3   8 14 43.750

我将使用我编写的ggcharts这一包来创建以上数据的条形图。ggcharts同时也提供了一个高级接口,可以用来使用ggplot2绘制图形。

library(ggcharts)
(p <- bar_chart(cyl, cyl, pct))

接下来,让我们使用scales中的percent()函数将坐标轴标签更改为百分号形式的。

p + scale_y_continuous(labels = scales::percent)

结果似乎有些出人意料! 4000% 远远超过了我们需要的值。其中的问题关键是在默认情况之下,scales::percent()将数据中的值都乘以了100。这个可以通过scale参数来控制。

scales::percent(100, scale = 1)
## [1] "100%"

然而,scale_y_continuous()中的labels参数期望的是一个函数而非一个实际的标签值作为其输入,引起使用percent()不是一个好的选项。不过好在scales包也提供了另一个percent_format()函数,它可以返回一个已经更改过默认值的percent()函数。

pct1 <- scales::percent_format(scale = 1)
pct1(100)
## [1] "100%"

将以上得到的函数传递给labels参数,于是可以得到我们想要的结果。

p + scale_y_continuous(labels = scales::percent_format(scale = 1))

另外,除了百分比外还可以只计算百分数。

cyl2 <- mtcars %>%
  count(cyl) %>%
  mutate(pct = n / sum(n))

bar_chart(cyl2, cyl, pct) +
  scale_y_continuous(labels = scales::percent)

但是值得注意的是结果中的小数位都是保留了一位小数,而我认为坐标轴的标签在小数位应该保持一致。

percent_format()函数中有一个参数accuracy是可以控制这一点的。

bar_chart(cyl2, cyl, pct) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1))

在我看来,以上的这些还是令人困惑(至少可以这样说)。因此,我认为有更好的解决方案,就是在数据中就计算出“比例”和“精度”。

我的解决方案是使用我编写的scalesextra包中的scale_y_pct()函数。

library(scalesextra)
bar_chart(cyl, cyl, pct) + scale_y_pct()

bar_chart(cyl2, cyl, pct) + scale_y_pct()

可以看到,不管数据是1的百分数还是百分比,都能正确地绘制。 此外,这两种情况都没有带小数位,与原始数据中的整数保持一致。

你还可以将scale_y_continuous()中的参数传递给scale_y_pct(),比如breaks

bar_chart(cyl, cyl, pct) + scale_y_pct(breaks = c(12.5, 30.75))

请注意,坐标轴中显示的小数位数对于所有标签都保持一致。小数位数将从数据值中的最高小数位数确定。而使用percent_format()则无法实现这一功能。

bar_chart(cyl, cyl, pct) +
  scale_y_continuous(
    labels = scales::percent_format(scale = 1),
    breaks = c(12.5, 30.75)
  )

scalesextra包尚处于早期开发阶段,因此只能从GitHub获得。 您可以通过在R控制台中运行以下这些命令来安装它。

if (!"remotes" %in% installed.packages()) {
  install.packages("remotes")
}
remotes::install_github("thomas-neitmann/scalesextra")

你可以测试scale_y_pct() (以及scale_x_pct()),如果有任何想法欢迎在评论中提出。此外,如果您发现任何错误(在早期开发的阶段),请在GitHub上发布。谢谢您的阅览!

本篇博客由Ivan Z翻译成中文,如您发现任何翻译上的错误请随时指正。非常感谢!