R 数据可视化 —— ggplot 标度(二)

3. 设置值范围

除了设置坐标轴的范围,我们也可以设置图形中必须包含某个或某些值。

可以使用 expand_limits() 函数,该函数接受一个命名列表,名称必须为图形属性

示例

对于下面这张散点图

p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
> mtcars %>% distinct(mpg) %>% summarise(min=min(.), max=max(.))
   min  max
1 10.4 33.9
> mtcars %>% distinct(wt) %>% summarise(min=min(.), max=max(.))
    min   max
1 1.513 5.424

从上面的结果中,我们可以计算出:X 轴(mpg)和 Y 轴(wt)的数据范围

下面,让我们用 expand_limits 来调整数据范围

p1 <- p + expand_limits(x = 0)

p2 <- p + expand_limits(y = c(1, 9))

p3 <- p + expand_limits(x = 0, y = 0)

plot_grid(p1, p2, p3, labels = c('A', 'B', 'C'), nrow = 1)

在图 A 中,我们设置 X 轴数据要包含 0,尽管并没有对应的值,但是 X 坐标轴还是会从 0 开始。

类似的,图 B 设置了 Y 轴需要包含 19,超过了数据的范围,相当于扩大了 Y 轴的范围

我们还可以对颜色进行设置

p1 <- ggplot(mtcars, aes(mpg, wt)) +
  geom_point(aes(colour = cyl)) +
  expand_limits(colour = seq(2, 10, by = 2))

p2 <- ggplot(mtcars, aes(mpg, wt)) +
  geom_point(aes(colour = factor(cyl))) +
  expand_limits(colour = factor(seq(2, 10, by = 2)))

plot_grid(p1, p2, labels = c('A', 'B'))

A 图设置了渐变色,B 图是离散配色。

> mtcars %>% distinct(cyl)
                  cyl
Mazda RX4           6
Datsun 710          4
Hornet Sportabout   8

我们可以看到,其实颜色的值只有三个 468,但是我们设置了 5 个不同的颜色层级。

B 图可以明显看出,210 的颜色并没有显示,因为不存在相应的数据

4. 设置间隔

可以使用 expansion() 函数设置数据与轴之间的间隔,该函数主要搭配 scale_(x|y)_continuousscale_(x|y)_discrete 使用。

# 推荐使用
expansion(mult = 0, add = 0)

# 已被弃用
expand_scale(mult = 0, add = 0)

该函数包含两个参数:

  • mult: 百分比间距,接受一个向量,如果向量长度为 1,则上下间距的间隔是一样的,如果长度为 2,则 mult[1] 为下间距,mult[2] 为上间距
  • add: 常数值单位间距,类似 mult

示例

p1 <- ggplot(mtcars) +
  geom_bar(aes(x = factor(cyl)))

p2 <- ggplot(mtcars) +
  geom_bar(aes(x = factor(cyl))) +
  scale_y_continuous(expand = expansion(mult = c(0, .1)))

p3 <- ggplot(subset(diamonds, carat > 2), aes(cut, clarity)) +
  geom_jitter() +
  scale_x_discrete(expand = expansion(add = 2))

p4 <- ggplot(subset(diamonds, carat > 2), aes(cut, price)) +
  geom_jitter() +
  scale_x_discrete(expand = expansion(add = .6)) +
  scale_y_continuous(expand = expansion(mult = .05))

plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4],
          nrow = 2)

其中,D 图所设置的间距是默认值

5. 设置透明度

alpha 透明度并不是非常有用,但它可以方便地从视觉上降低不太重要的观察结果的权重

设置透明度的函数包括:

scale_alpha(..., range = c(0.1, 1))

scale_alpha_continuous(..., range = c(0.1, 1))

scale_alpha_binned(..., range = c(0.1, 1))

scale_alpha_discrete(...)

scale_alpha_ordinal(..., range = c(0.1, 1))

其中 scale_alphascale_alpha_continuous 的别名,因为这个函数是最常用的。

其中 range 参数的值为透明度的范围,必须在 0-1 之间。

其他参数分别被 continuous_scale(), binned_scale, 和 discrete_scale() 解析

示例

首先在 aes 中设置透明度,如

p <- ggplot(mpg, aes(displ, hwy)) +
  geom_point(aes(alpha = year))

然后使用标度函数来修改透明度范围

p1 <- p + scale_alpha("cylinders")

p2 <- p + scale_alpha(range = c(0.4, 0.8))

plot_grid(p1, p2, labels = LETTERS[1:2],
          nrow = 1)

在图 A 中,我们传递了一个字符串,相当于设置了 name 参数的值,更改了图例的名称

自定义透明度

p <- ggplot(mpg, aes(displ, hwy)) +
  geom_point(aes(alpha = factor(year)))

p + scale_alpha_manual(values = c(0.1, 0.2))

6. 设置线条类型

线条的类型可以使用 0-6 之间的整数来指定,分别代表

0 = blank         1 = solid
2 = dashed        3 = dotted
4 = dotdash       5 = longdash
6 = twodash

绘制所有的线条类型

df_lines <- tibble(
  linetype = factor(0:6)
)

ggplot(df_lines) +
  geom_hline(aes(linetype = linetype, yintercept = 0), size = 2) +
  scale_linetype_discrete() +
  facet_grid(linetype ~ .) +
  theme_void(20)

线条类型不支持连续型数据,因为无法将连续型数据映射到线型。但是可以使用 scale_linetype_binned(),由于线型没有固定的顺序,也不推荐这样使用

示例

对于数据

> economics_long
# A tibble: 2,870 x 4
   date       variable value  value01
   <date>     <chr>    <dbl>    <dbl>
 1 1967-07-01 pce       507. 0       
 2 1967-08-01 pce       510. 0.000265
 3 1967-09-01 pce       516. 0.000762
 4 1967-10-01 pce       512. 0.000471
 5 1967-11-01 pce       517. 0.000916
 6 1967-12-01 pce       525. 0.00157 
 7 1968-01-01 pce       531. 0.00207 
 8 1968-02-01 pce       534. 0.00230 
 9 1968-03-01 pce       544. 0.00322 
10 1968-04-01 pce       544  0.00319 
# … with 2,860 more rows

我们根据 variable 变量进行分组,绘制折线图

base <- ggplot(economics_long, aes(date, value01))
base + geom_line(aes(group = variable))

注意:我们是通过设置 group = variable 来设置分组的,但是组与组之间没有区分度。

为图片添加线型和颜色

base + geom_line(aes(linetype = variable, colour=variable))

这样,每组之间的趋势就很明显了。

自定义线条映射

df <- economics_long %>% filter(variable %in% c("pop", "pce", "uempmed")) 

lt <- c("pop"=1, "pce"=3, "uempmed"=5)

ggplot(df, mapping = aes(date, value01)) +
  geom_line(aes(linetype = variable, colour=variable)) +
  scale_linetype_manual(values = lt)

7. 设置形状

scale_shape() 函数可以将离散变量映射为 6 个不同的形状。

如果你有超过 6 个类别,你将会得到一个警告信息,并且第 7 个或更后面的类别将不会在图片中显示

形状与线型一样,不支持连续型数据,也不推荐使用 scale_shape_binned 函数来设置

scale_shape(..., solid = TRUE)

scale_shape_binned(..., solid = TRUE)

其中 solid 参数控制形状是不是实心的

下面的代码展示了所有的形状

df_shapes <- data.frame(shape = 0:25)

ggplot(df_shapes, aes(0, 0, shape = shape)) +
  geom_point(aes(shape = shape), size = 5, fill = 'red') +
  scale_shape_identity() +
  facet_wrap(~shape) +
  theme_void()

取值范围为 0-25,共 26 个整数值分别代表了相应的形状。

注意:红色的形状是可以设置填充色(fill)的,其他形状只能设置轮廓颜色(colour)。

示例

dsmall <- diamonds[sample(nrow(diamonds), 100), ]

d <- ggplot(dsmall, aes(carat, price)) + geom_point(aes(shape = cut))

p2 <- d + scale_shape(solid = FALSE)

p3 <- d + scale_shape(name = "Cut of diamond")

levels(dsmall$cut) <- c("Fair", "Good", "Very Good", "Premium", "Ideal")
p4 <- ggplot(dsmall, aes(price, carat)) + geom_point(aes(shape = cut))

plot_grid(d, p2, p3, p4, labels = LETTERS[1:4])

注意:在绘制图 D 时,会输出警告信息,提示不建议对排序的变量设置形状

自定义形状映射

shape_map <- c("Fair"=13, "Good"=20, "Very Good"=15, "Premium"=2, "Ideal"=11)

d + scale_shape(solid = FALSE) +
  scale_shape_manual(values = shape_map)

8. 设置大小

一般只有点图和文本需要设置大小。而我们通常是将数据映射到点的面积,而不是映射到半径。

标度函数如下

scale_size(..., range = c(1, 6))

scale_radius(..., range = c(1, 6))

scale_size_binned(..., range = c(1, 6))

scale_size_area(..., max_size = 6)

scale_size_binned_area(..., max_size = 6)

如果需要将值为 0 的点映射为 0,需要使用 scale_size_area 函数

示例

例如,下面这张散点图

p <- ggplot(mpg, aes(displ, hwy, size = hwy)) +
  geom_point()
# 设置图例标题
p1 <- p + scale_size("Highway mpg")

# 设置点的大小范围
p2 <- p + scale_size(range = c(0, 10))

# 允许将 0 值映射为面积为 0 的点(不绘制)
p3 <- p + scale_size_area()

# 方便从看出图例中看出分箱
p4 <- p + scale_size_binned()

# This is most useful when size is a count
p5 <- ggplot(mpg, aes(class, cyl)) +
  geom_count() +
  scale_size_area()

# 将数据映射为半径,不推荐
p6 <- p + scale_radius()

plot_grid(p1, p2, p3, p4, p5, p6,
          labels = LETTERS[1:6], nrow = 3)

自定义数据大小,我们根据 cyl 的值倒序设置点的大小

ggplot(mpg, aes(displ, hwy, size = factor(cyl))) +
  geom_point() +
  scale_size_manual(
    name="cyl",
    values = c(
    "4" = 5,
    "5" = 4,
    "6" = 3,
    "8" = 2
  ))
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容