9.1 条形图与线图

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 数据集):

dat <- data.frame(time = factor(c("Lunch", "Dinner"), levels = c("Lunch",
  "Dinner")), total_bill = c(14.89, 17.23))
dat
#>     time total_bill
#> 1  Lunch      14.89
#> 2 Dinner      17.23

## 导入 ggplot2 分析包
library(ggplot2)

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

这里使用的映射变量为:

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

9.1 条形图与线图 - 图1

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

9.1 条形图与线图 - 图2

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

9.1 条形图与线图 - 图3

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

9.1 条形图与线图 - 图4

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

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

9.1 条形图与线图 - 图5

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

9.1.2.1.2 计数的条形图

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

我们直接使用 reshape2 的 tips 数据集。

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

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

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

9.1 条形图与线图 - 图6

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

9.1.2.2 线图

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

下面是使用的映射变量:

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

9.1 条形图与线图 - 图7

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

9.1 条形图与线图 - 图8

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

9.1 条形图与线图 - 图9

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

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

9.1 条形图与线图 - 图10

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

9.1.3 有更多变量的图

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

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

9.1.3.1 条形图

变量映射:

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

9.1 条形图与线图 - 图11

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

9.1 条形图与线图 - 图12

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

9.1 条形图与线图 - 图13

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

9.1 条形图与线图 - 图14

改变映射是非常容易的:

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

9.1 条形图与线图 - 图15

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

9.1.3.2 线图

变量映射:

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

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

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

9.1 条形图与线图 - 图16

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

9.1 条形图与线图 - 图17

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

9.1 条形图与线图 - 图18

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

9.1 条形图与线图 - 图19

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

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

9.1 条形图与线图 - 图20

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

9.1.3.3 完成的例子

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

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

9.1 条形图与线图 - 图21

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

9.1 条形图与线图 - 图22

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

9.1.4 使用数值 x-axis

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

datn <- read.table(header = TRUE, text = "
supp dose length
  OJ  0.5  13.23
  OJ  1.0  22.70
  OJ  2.0  26.06
  VC  0.5   7.98
  VC  1.0  16.77
  VC  2.0  26.14
")

来自 ToothGrowth 数据集。

9.1.4.1 x-axis 作为连续变量

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

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

9.1 条形图与线图 - 图23

9.1.4.2 x-axis 作为分类变量

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

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

9.1 条形图与线图 - 图24

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

9.1 条形图与线图 - 图25

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

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

9.1 条形图与线图 - 图26


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

9.1 条形图与线图 - 图27