R统计图表与好玩的字体

  本文参考至统计之都的showtext:字体,好玩的字体和好玩的图形以及R能不能绘制这种图形??。当中讨论了在R图表中显示中文以及其他自定义字体的方法。这两篇文章中使用到showtext这个包,但实际测试发现好像不使用showtext也能达到同样的效果。下面的R code我是在Mac下的RStudio下实验的,因此如果windows达不到同样的效果,可以参考上面这两篇文章。

  正常情况下,R plot不能显示中文,所有中文会变成一个一个方块

1
plot(cars, main = "中文")

  这是因为R无法找到正确的中文字体来显示。简单设置一下字体之后,发现中文标题可以正常显示了。这里”Kai”是系统自带的楷体字。

1
plot(cars, main = "中文标题", family = "Kai")

  不仅仅是标题,我们往plot上增加的text也是可以设置中文字体的。

1
2
3
4
5
6
set.seed(123)
plot(1, xlim = c(-3, 3), ylim = c(-3, 3), type = "n")
text(runif(7, -3, 3), runif(7, -3, 3), labels = c("内", "容", "设", "置",
"为", "宋", "体"), col = rgb(runif(7), runif(7), runif(7)), cex = 2,
family = "Songti SC")
title("楷体的标题", family = "Kai")

  那么我们自己下载的字体可不可以呢?答案是可以的。如果不想安装字体,可以按照文章一开始参考的链接,使用showtext包来载入字体。或者跟我一样先安装字体,这样使用起来就和系统自带的字体一样了。
  接下来我们来画一个不同教育程度下性别比例的横向柱状图。首先下载wmpeople1字体。在这种字体下字母”p”将显示为男人,”u”将显示为女人。
  下载并解压,会得到一个叫wmpeople1.TTF的字体文件。在Mac下直接双击该字体文件即可安装。

  先来看看原始数据:

edu educode gender population
未上过学 1 m 17464
未上过学 1 f 41268
小 学 2 m 139378
小 学 2 f 154854
初 中 3 m 236369
初 中 3 f 205537
高 中 4 m 94528
高 中 4 f 70521
大专及以上 5 m 57013
大专及以上 5 f 50334

  其中人口的单位为(千人),之后会先除以10000转换为(千万人)。
  接下来我们将使用ggplot2画图。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
library(ggplot2)
library(plyr)
# 用来产生图形的模拟数据
dat = read.csv(textConnection('
edu,educode,gender,population
未上过学,1,m,17464
未上过学,1,f,41268
小 学,2,m,139378
小 学,2,f,154854
初 中,3,m,236369
初 中,3,f,205537
高 中,4,m,94528
高 中,4,f,70521
大专及以上,5,m,57013
大专及以上,5,f,50334
'));
dat$int = round(dat$population / 10000);
# 利用plyr::ddply整理数据。我们需要得到整张图中每个小人所站的坐标,以及
# 该坐标小人的样式(男生or女生)
# 1.按照教育程度"educode"切分数据
# 2.获取对应教育程度下男生和女生的数量。并转换为横坐标的值
# 例如未上过学 educode=1当中,男生数为2,女生数为4。则我们应该产生6个坐标点,
# 这6个左边点的y轴均为1(educode),x轴分别为1,2,3,4,5,6,其中x=1,2为男生,
# x = 3,4,5,6为女生
gdat = ddply(dat, "educode", function(d) {
male = d$int[d$gender == "m"]
female = d$int[d$gender == "f"]
data.frame(gender = c(rep("m", male), rep("f", female)),
x = 1:(male + female))
});
# wmpeople1字体下p显示为男人,u显示为女人,因此把性别的字母做一下转换
gdat$char = ifelse(gdat$gender == "m", "p", "u");
theme_set(theme_grey(base_size = 15))
ggplot(gdat, aes(x = x, y = educode)) + # 设置横坐标为x,纵坐标为教育程度
geom_text(aes(label = char, colour = gender),
family = "wmpeople1", size = 8) + # 设置文字字体、大小与颜色
scale_x_continuous("\n人数(千万)") +
scale_y_discrete("受教育程度\n",
labels = unique(dat$edu[order(dat$educode)])) +
scale_colour_hue(guide = FALSE) +
ggtitle("2012年人口统计数据\n") +
theme(text=element_text(family='Songti SC')) # 设置标题与坐标轴的字体

  标题,横纵坐标的label,以及内部的text都可以修改字体。那么坐标轴上的文字当然也是可以的。
  我们来把教育程度改成暴走字体。和之前一样下载解压,得到一个Memes.ttf的字体文件,安装它。不过注意安装之后该字体的名称并不是叫Memes,如果像之前一样把字体设置为Memes会报错说找不到字体。

  安装的时候我们可以看到该字体真实的名字叫做adasdasdsdsd(看名字就够暴走了。。。)

  我们这里试着把纵坐标替换为暴走体,因为暴走字体只支持英文大小写以及数字,因此先把这几个教育程度替换为英文字母。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 把edu(中文)转为educhar(字母)
educhar = letters[dat$educode]
ggplot(gdat, aes(x = x, y = educode)) +
geom_text(aes(label = char, colour = gender),
family = "wmpeople1", size = 7) +
scale_x_continuous("\n人数(千万)") +
scale_y_discrete("受教育程度\n",
labels = unique(educhar[order(dat$educode)])) + # 注意这一行与之前的不同,把dat$edu换为educhar
scale_colour_hue(guide = FALSE) +
ggtitle("2012年统计数据\n") +
theme(axis.text.y=element_text(size=rel(4), family="adasdasdsdsd"), # 纵坐标为暴走体
text=element_text(family='Songti SC')) # 标题以及坐标名称为宋体

喜欢就分享一下吧