9.1 条形图与线图

9.1.1 问题

你想要创建基本的条形图与线图

9.1.2 方案

想要使用 ggplot2 绘制图形,数据必须是一个数据框,而且必须是长格式。

9.1.2.1 基本图形,离散 x-axis

使用条形图,条形的高度通常代表这种不同的东西:

  • 每一组事件的计数,通过 stat_bin() 指定,ggplot2 默认使用该选项
  • 数据集中某一列的,通过 stat_identity() 指定
x 轴高度含义名称
连续计数直方图
离散计数条形图
连续数值条形图
离散数值条形图
9.1.2.1.1 有值的条形图

这里有一些样例数据 (抽自 reshape2 包的 tips 数据集):

  1. dat <- data.frame(time = factor(c("Lunch", "Dinner"), levels = c("Lunch",
  2. "Dinner")), total_bill = c(14.89, 17.23))
  3. dat
  4. #> time total_bill
  5. #> 1 Lunch 14.89
  6. #> 2 Dinner 17.23
  7. # 导入 ggplot2 分析包
  8. library(ggplot2)

在这些例子中,条形的高度代表数据框某一列的,所以使用 stat="identity" 而不是默认的 stat="bin"

这里使用的映射变量为:

  • time: x-axis 和填充颜色
  • total_bill: y-axis
  1. # 非常基本的条形图
  2. ggplot(data = dat, aes(x = time, y = total_bill)) + geom_bar(stat = "identity")

9.1 条形图与线图 - 图1

  1. # 按时间填充颜色
  2. ggplot(data = dat, aes(x = time, y = total_bill, fill = time)) +
  3. geom_bar(stat = "identity")

9.1 条形图与线图 - 图2

  1. ## 这和上面是一样的结果 ggplot(data=dat, aes(x=time,
  2. ## y=total_bill)) + geom_bar(aes(fill=time),
  3. ## stat='identity') 添加黑色的边框线
  4. ggplot(data = dat, aes(x = time, y = total_bill, fill = time)) +
  5. geom_bar(colour = "black", stat = "identity")

9.1 条形图与线图 - 图3

  1. # 没有图例,因为这个信息是多余的
  2. ggplot(data = dat, aes(x = time, y = total_bill, fill = time)) +
  3. geom_bar(colour = "black", stat = "identity") + guides(fill = FALSE)

9.1 条形图与线图 - 图4

一个理想的条形图可能是下面这样的:

  1. # 添加题目,缩小箱宽,填充颜色,改变轴标签
  2. ggplot(data = dat, aes(x = time, y = total_bill, fill = time)) +
  3. geom_bar(colour = "black", fill = "#DD8888", width = 0.8,
  4. stat = "identity") + guides(fill = FALSE) + xlab("Time of day") +
  5. ylab("Total bill") + ggtitle("Average bill for 2 people")

9.1 条形图与线图 - 图5

查看颜色获取更多关于颜色的信息。

9.1.2.1.2 计数的条形图

在下面例子中,条形高度代表事件的计数。

我们直接使用 reshape2tips 数据集。

  1. library(reshape2)
  2. # 查看头几行
  3. head(tips)
  4. #> total_bill tip sex smoker day time size
  5. #> 1 16.99 1.01 Female No Sun Dinner 2
  6. #> 2 10.34 1.66 Male No Sun Dinner 3
  7. #> 3 21.01 3.50 Male No Sun Dinner 3
  8. #> 4 23.68 3.31 Male No Sun Dinner 2
  9. #> 5 24.59 3.61 Female No Sun Dinner 4
  10. #> 6 25.29 4.71 Male No Sun Dinner 4

想要得到一个计数的条形图,不要映射变量到 y,使用 stat="bin" (默认就是这个) 而不是 stat="identity":

  1. # 计数的条形图
  2. ggplot(data = tips, aes(x = day)) + geom_bar(stat = "count")

9.1 条形图与线图 - 图6

  1. ## 和上面等同, 因为 stat='bin' 是默认 ggplot(data=tips,
  2. ## aes(x=day)) + geom_bar()

9.1.2.2 线图

对于线图,数据点必须分组从而 R 知道怎么连接这些点。如果只有一组的话,非常简单,设定 group=1 即可,如果是多组,需要设定分组变量。

下面是使用的映射变量:

  • time: x 轴
  • total_bill: y 轴
  1. # 基本的线图
  2. ggplot(data = dat, aes(x = time, y = total_bill, group = 1)) +
  3. geom_line()

9.1 条形图与线图 - 图7

  1. ## 与上面结果一致 ggplot(data=dat, aes(x=time,
  2. ## y=total_bill)) + geom_line(aes(group=1)) 添加点
  3. ggplot(data = dat, aes(x = time, y = total_bill, group = 1)) +
  4. geom_line() + geom_point()

9.1 条形图与线图 - 图8

  1. # 改变线和点的颜色
  2. # 改变线的类型和点的类型,用更粗的线、更大的点
  3. # 用红色填充点
  4. ggplot(data = dat, aes(x = time, y = total_bill, group = 1)) +
  5. geom_line(colour = "red", linetype = "dashed", size = 1.5) +
  6. geom_point(colour = "red", size = 4, shape = 21, fill = "white")

9.1 条形图与线图 - 图9

理想的线图可能像下面这样:

  1. # 设定 y 轴的范围 改变轴标签
  2. ggplot(data = dat, aes(x = time, y = total_bill, group = 1)) +
  3. geom_line() + geom_point() + expand_limits(y = 0) +
  4. xlab("Time of day") + ylab("Total bill") + ggtitle("Average bill for 2 people")

9.1 条形图与线图 - 图10

查看颜色获取更多关于颜色的信息。查看形状与线形 获取更多相关内容。

9.1.3 有更多变量的图

下面这个数据将用于接下来的例子

  1. dat1 <- data.frame(sex = factor(c("Female", "Female", "Male",
  2. "Male")), time = factor(c("Lunch", "Dinner", "Lunch",
  3. "Dinner"), levels = c("Lunch", "Dinner")), total_bill = c(13.53,
  4. 16.81, 16.24, 17.42))
  5. dat1
  6. #> sex time total_bill
  7. #> 1 Female Lunch 13.53
  8. #> 2 Female Dinner 16.81
  9. #> 3 Male Lunch 16.24
  10. #> 4 Male Dinner 17.42

9.1.3.1 条形图

变量映射:

  • time: x 轴
  • sex: 颜色填充
  • total_bill: y 轴
  1. # 堆积条形图 -- 不常用
  2. ggplot(data = dat1, aes(x = time, y = total_bill, fill = sex)) +
  3. geom_bar(stat = "identity")

9.1 条形图与线图 - 图11

  1. # 条形图,x 轴是 time, 颜色填充是 sex
  2. ggplot(data = dat1, aes(x = time, y = total_bill, fill = sex)) +
  3. geom_bar(stat = "identity", position = position_dodge())

9.1 条形图与线图 - 图12

  1. ggplot(data = dat1, aes(x = time, y = total_bill, fill = sex)) +
  2. geom_bar(stat = "identity", position = position_dodge(),
  3. colour = "black")

9.1 条形图与线图 - 图13

  1. # 改变颜色
  2. ggplot(data = dat1, aes(x = time, y = total_bill, fill = sex)) +
  3. geom_bar(stat = "identity", position = position_dodge(),
  4. colour = "black") + scale_fill_manual(values = c("#999999",
  5. "#E69F00"))

9.1 条形图与线图 - 图14

改变映射是非常容易的:

  1. # 条形图,x 轴是性别,颜色是时间
  2. ggplot(data = dat1, aes(x = sex, y = total_bill, fill = time)) +
  3. geom_bar(stat = "identity", position = position_dodge(),
  4. colour = "black")

9.1 条形图与线图 - 图15

查看颜色获取更多关于颜色的信息。

9.1.3.2 线图

变量映射:

  • time: x 轴
  • sex: 线的颜色
  • total_bill: y 轴

想要绘制多条线,必须指定分组变量,否则所有点都将通过一条线进行连接。在这个例子中,我们希望通过性别来进行分组。

  1. # 基本的带点线图
  2. ggplot(data = dat1, aes(x = time, y = total_bill, group = sex)) +
  3. geom_line() + geom_point()

9.1 条形图与线图 - 图16

  1. # 将性别映射到颜色
  2. ggplot(data = dat1, aes(x = time, y = total_bill, group = sex,
  3. colour = sex)) + geom_line() + geom_point()

9.1 条形图与线图 - 图17

  1. # 映射性别到不同的点类型
  2. ggplot(data = dat1, aes(x = time, y = total_bill, group = sex,
  3. shape = sex)) + geom_line() + geom_point()

9.1 条形图与线图 - 图18

  1. # 使用更粗的线、更大的点
  2. ggplot(data = dat1, aes(x = time, y = total_bill, group = sex,
  3. shape = sex)) + geom_line(size = 1.5) + geom_point(size = 3,
  4. fill = "white") + scale_shape_manual(values = c(22,
  5. 21))

9.1 条形图与线图 - 图19

更改颜色和线型变量的映射非常容易:

  1. ggplot(data = dat1, aes(x = sex, y = total_bill, group = time,
  2. shape = time, color = time)) + geom_line() + geom_point()

9.1 条形图与线图 - 图20

查看颜色获取更多关于颜色的信息。查看形状与线形获取更多相关内容。

9.1.3.3 完成的例子

完成的例子可能像下面这样:

  1. # 一个条形图
  2. ggplot(data=dat1, aes(x=time, y=total_bill, fill=sex)) +
  3. geom_bar(colour="black", stat="identity",
  4. position=position_dodge(),
  5. size=.3) + # 更粗的线
  6. scale_fill_hue(name="Sex of payer") + # 设定图例标题
  7. xlab("Time of day") + ylab("Total bill") + # 设定轴标签
  8. ggtitle("Average bill for 2 people") + # 设定题目
  9. theme_bw()

9.1 条形图与线图 - 图21

  1. # 一个线图
  2. ggplot(data=dat1, aes(x=time, y=total_bill, group=sex, shape=sex, colour=sex)) +
  3. geom_line(aes(linetype=sex), size=1) + # 按性别设定线型
  4. geom_point(size=3, fill="white") + # 使用更大的点,并用颜色填充
  5. expand_limits(y=0) + # 将 0 包含仅 y 轴
  6. scale_colour_hue(name="Sex of payer", # 设定图例标题
  7. l=30) + # 使用更深的颜色 (lightness=30)
  8. scale_shape_manual(name="Sex of payer",
  9. values=c(22,21)) + #
  10. scale_linetype_discrete(name="Sex of payer") +
  11. xlab("Time of day") + ylab("Total bill") + # 设定轴标签
  12. ggtitle("Average bill for 2 people") + # 设定标题
  13. theme_bw() +
  14. theme(legend.position=c(.7, .4)) # 图例的位置

9.1 条形图与线图 - 图22

为了保证上图的图例一致,必须指定 3 次。至于为何如此,查看图例

9.1.4 使用数值 x-axis

当 x 轴上的变量是数字时,有时需要将其视为连续变量,有时需要将其视为分类变量。在该数据集中,剂量应该是值为 0.5, 1.02.0 的数值变量。作图时,将这些值视为相同类别可能很有用。

  1. datn <- read.table(header = TRUE, text = "
  2. supp dose length
  3. OJ 0.5 13.23
  4. OJ 1.0 22.70
  5. OJ 2.0 26.06
  6. VC 0.5 7.98
  7. VC 1.0 16.77
  8. VC 2.0 26.14
  9. ")

来自 ToothGrowth 数据集。

9.1.4.1 x-axis 作为连续变量

一个简单的图形可能会将剂量放在 x 轴,这种方式可以绘制一个线图。

  1. ggplot(data = datn, aes(x = dose, y = length, group = supp,
  2. colour = supp)) + geom_line() + geom_point()

9.1 条形图与线图 - 图23

9.1.4.2 x-axis 作为分类变量

首先,我们要将该变量转换为因子。

  1. # 拷贝数据框并将它转换为因子
  2. datn2 <- datn
  3. datn2$dose <- factor(datn2$dose)
  4. ggplot(data = datn2, aes(x = dose, y = length, group = supp,
  5. colour = supp)) + geom_line() + geom_point()

9.1 条形图与线图 - 图24

  1. # 使用原始的数据框,但使用 factor 函数在绘图时转换
  2. ggplot(data = datn, aes(x = factor(dose), y = length, group = supp,
  3. colour = supp)) + geom_line() + geom_point()

9.1 条形图与线图 - 图25

当连续值作为分类变量使用时,也可以绘制条形图。

  1. ggplot(data = datn2, aes(x = dose, y = length, fill = supp)) +
  2. geom_bar(stat = "identity", position = position_dodge())

9.1 条形图与线图 - 图26

  1. ggplot(data = datn, aes(x = factor(dose), y = length, fill = supp)) +
  2. geom_bar(stat = "identity", position = position_dodge())

9.1 条形图与线图 - 图27