颜林林的个人网站

Linlin Yan's Personal Website

[不靠谱颜论] 用ggplot2给娃手工做张九九乘法表

2020-07-11 02:44

导言: 只要肯折腾,ggplot2还是有很多花式玩法的……


缘起

2020年,受疫情影响,无数家庭意外收获了大量亲子时光。线上教育也顺势蓬勃发展,帮助家长们管束神兽,使不至于把房顶全都掀翻。我家小闺女早已不满足于20以内的加减法,于是前些天,我突发奇想开始教她乘法,并背诵起九九乘法表来。

然而,在家里找了一圈各类绘本与书籍,竟然都没有找到一张九九表。作为闲不住就想写写代码的我,自然而然地就想,能不能简单写上几行代码,来快速搞定它。

说干就干,这就动手做起来。

实现

首先,得选择合适的语言工具。由于目的是“绘制”九九表,我第一时间想到的,当然就是R语言的ggplot2包了,它是当之无愧的统计绘图第一利器。

附注:`ggplot2`基于一套称为图形语法(The Grammar Of Graphics)的理论体系定义,将图形呈现方式独立且优雅地抽象出来,使得在数据探索及其可视化的过程中,可以随时随地任意调整数据变量与图形元素的绑定关系,让同一组数据在大相径庭的多种统计图之间快速切换,帮助寻找数据规律,因而被广泛使用。

然后,在绘图之前,需要先把数据准备好。ggplot2要求输入数据采用数据框(data.frame)的类型,通常更推荐使用其替代品,即dplyr包中提供的tibble类型。ggplot2dplyr,可通过加载tidyverse包,来一次性将其全都载入使用。为了构造形如“A x B = C”的式子,我们可以使用expand.grid函数来构造所有组合,并使用filter函数过滤选出最终九九表中需要的下三角部分:

1
2
library(tidyverse)
a <- expand.grid(A = 1:9, B = 1:9) %>% filter(A <= B)

接着,我们就可以使用ggplot2中的geom_tilegeom_text函数,来绘制相应的表格及等式了:

1
2
3
4
a %>% ggplot(aes(A, 9 - B)) +
  geom_tile(color = "black", fill = NA) +
  geom_text(aes(label = sprintf("%d x %d = %d", A, B, A * B))) +
  theme_void()

然而,这里得到的九九表,只有数字算式,而没有中文口诀。为了构造中文口诀,需要另外设计一两个辅助函数来帮助实现:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
a <- "一二三四五六七八九十"
a <- strsplit(a, "")[[1]] # 拆分出每个汉字

ch <- function(x) { # 构造一个函数,能将单个数字转换成汉字
  if (x < 10) {
    a[[x]]
  } else {
    paste0(a[[x %/% 10]], a[[10]],
           if (x %% 10 > 0) a[[x %% 10]])
  }
}
ch <- Vectorize(ch) # 函数向量化。原函数只能支持单个数字的处理
                    # 经此处理,函数就能支持以向量作为输入参数

于是,最终ggplot调用变为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
expand.grid(A = 1:9, B = 1:9) %>%
  filter(A <= B) %>%
  ggplot(aes(A, 9 - B)) +
  geom_tile(aes(fill = as.factor(A + B)),
            color = "black", size = .5) +
  geom_text(aes(label = sprintf("%d x %d = %d\n%s%s%s%s",
                                A, B, A * B, ch(A), ch(B),
                                ifelse(A*B<10,"得",""),
                                ch(A*B))),
                size = 5, lineheight = 1) +
  guides(fill = FALSE) +
  theme_void()

其呈现效果如下所示(长按该图片可以跳转至对应github仓库):

其他

ggplot2具有极强的视觉展示能力。通常,只需把相应数据构造好,然后指定合适的geom函数,就能快速定制出各种效果理想的图形来。

此外,若再结合gglocatorgetGraphicsEvent这样的接收鼠标或键盘输入的函数,就能搞出一堆交互式的玩法来。

下面举几个我曾经用ggplot2搞出来的小玩意儿,供体会下“不务正业的R”之魅力:

  1. 键盘指法练习:

    https://github.com/yanlinlin82/kids.typing

  2. 连连看:

    https://github.com/yanlinlin82/link-game-in-r

  3. 2048:

    https://github.com/yanlinlin82/r-2048

本文意在抛砖引玉,欢迎大家多多折腾,让学习和生活都变得更丰富有趣!

--- END ---

注:本文发表于“不靠谱颜论”公众号,并同步至本站。