ggplot2柱状图按数值大小排序

ggplot2柱状图按照数值大小进行排序是比较困难的。这是因为ggplot2考虑的是因子级别的顺序,而不是数据框中观察到的顺序。我们可以使用sort()arrange()对输入数据框进行排序,但是这不会对ggplot2输出产生任何影响(柱状图依旧按照因子的顺序排列)。

本文主要介绍如何让ggplot2的柱状图按照数值大小排序。

本文用到的数据集

数据集1——自己定义的:

1
2
3
4
data <- data.frame(
name = c("north","south","south-east","north-west","south-west","north-east","west","east"),
val=sample(seq(1,10), 8)
)

数据集2——ggplot2包自带的mpg数据集。

forecats包实现

forecats库是tidyverse中的一个库,专门用于处理R中的因子,它提供了一组有用的工具来解决因子的常见问题。其中fact_reorder()函数允许通过另一列data$val的值对因子data$name进行重新排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
library(ggplot2)
library(dplyr)
library(forcats)

# 通过另一列的值来对因子重新排序(升序)
data %>%
mutate(name = fct_reorder(name, val)) %>%
ggplot(aes(x=name, y=val)) +
geom_bar(stat="identity", fill="#f68060", alpha=.6, width=.4) +
coord_flip() +
xlab("") +
theme_bw()

# 通过另一列的值来对因子重新排序(降序)
data %>%
mutate(name = fct_reorder(name, desc(val))) %>%
ggplot(aes(x=name, y=val)) +
geom_bar(stat="identity", fill="#f68060", alpha=.6, width=.4) +
coord_flip() +
xlab("") +
theme_bw()

我们可以指定用哪个函数.fun来确定顺序。默认值是使用中位数,我们也可以使用每组的数据点数来排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 中位数(默认)
mpg %>%
mutate(class = fct_reorder(class, hwy, .fun='median')) %>%
ggplot(aes(x=class, y=hwy, fill=class)) +
geom_boxplot() +
xlab("class") +
theme(legend.position="none") +
xlab("")

# 数据点数
mpg %>%
mutate(class = fct_reorder(class, hwy, .fun='length')) %>%
ggplot(aes(x=class, y=hwy, fill=class)) +
geom_boxplot() +
xlab("class") +
theme(legend.position="none") +
xlab("")

当然我们也可以自己指定因子的顺序:

1
2
3
4
5
6
7
8
data %>%
mutate(name = fct_relevel(name,
"north", "north-east", "east",
"south-east", "south", "south-west",
"west", "north-west")) %>%
ggplot( aes(x=name, y=val)) +
geom_bar(stat="identity") +
xlab("")

dplyr包实现

dplyrmutate()函数允许创建新变量或修改现有变量,我们可以用它来重新创建具有特定顺序的因子。下面是两个例子:

  • 采用arrange()对数据框进行排序,然后按照这个顺序对因子进行重新排序。
  • 自定义因子顺序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 利用arrange()对数据框排序,然后按照这个顺序对因子进行重新排序
data %>%
# 按照val进行排序,但是这只对数据框进行了排序而没有对因子进行排序
arrange(val) %>%
# 通过下面这个小技巧可以直接更新因子
mutate(name=factor(name, levels=name)) %>%
ggplot(aes(x=name, y=val)) +
geom_segment(aes(xend=name, yend=0)) +
geom_point(size=4, color="orange") +
coord_flip() +
theme_bw() +
xlab("")

# 自定义因子顺序
data %>%
arrange(val) %>%
mutate(name = factor(name, levels=c("north", "north-east", "east", "south-east", "south", "south-west", "west", "north-west"))) %>%
ggplot(aes(x=name, y=val)) +
geom_segment(aes(xend=name, yend=0)) +
geom_point(size=4, color="orange") +
theme_bw() +
xlab("")

base包的reorder()函数实现

reorder()函数用法:

1
reorder(x, X, FUN = mean, ..., order = is.ordered(x))
  • x:因子型向量
  • X:用来排序的数值型向量
  • FUN:汇总数据的函数
  • ...FUN的参数(可选)
  • order:我们可以通过这个参数直接指定因子型向量的顺序

按照x对X进行分组,对每一组组成的向量计算后面的函数,最后根据计算结果从小到大指定x中元素的顺序。

下面是一个例子:

1
2
3
4
5
6
7
8
mpg$class = with(mpg, reorder(class, hwy, median))

p <- mpg %>%
ggplot( aes(x=class, y=hwy, fill=class)) +
geom_violin() +
xlab("class") +
theme(legend.position="none") +
xlab("")

参考


----------- 本文结束啦感谢您阅读 -----------

赞赏一杯咖啡