绘制简单直方图
问题
如何绘制直方图?
方法
运行geom_histogram() 函数并映射一个连续型变量到参数x(见图6-1):
ggplot(faithful, aes(x=waiting)) + geom_histogram()
讨论
geom_histogram() 函数只需要数据框的其中一列或者一个单独的数据向量作为参数。以faithful 数据集为例,该数据集包含了两列描述老忠实喷泉的信息:第一列eruptions,描述老忠实喷泉每次喷发的时长;第二列waiting,描述两次喷发之间的间隔。下面仅以列waiting 为例:
faithful
eruptions waiting
3.600 79
1.800 54
3.333 74
...
如果想快速地看一下未包含在数据框中的数据的直方图,可以在运行上述命令时, 将数据框参数设定为NULL,同时,向ggplot() 函数传递一个向量作为参数。下面的代码与之前的运行结果相同:
# 将变量值保存为一个基本向量
w <-faithful$waiting
ggplot(NULL, aes(x=w)) + geom_histogram()
默认情况下,数据将被切分为30 组,这样分组可能太过精细,也可能太过粗糙,这取决于数据的实际情况。我们可以通过组距(binwidth)参数来调整数据的分组数目,或者将数据切分为指定的分组数目。直方图默认的填充色是黑色且没有边框线,这使得我们难以看清各个条形对应的变量值,因此,可以调整一下直方图的颜色设置,如图6-2 所示:
# 设定组距为5
ggplot(faithful, aes(x=waiting)) +
geom_histogram(binwidth=5, fill="white", colour="black")
# 将x 的取值切分为15 组
binsize <- diff(range(faithful$waiting))/15
ggplot(faithful, aes(x=waiting)) +
geom_histogram(binwidth=binsize, fill="white", colour="black")
有时,直方图的外观会非常依赖于组距及组边界。图6-3 中,我们将组距设定为8。同时设定分组原点(origin)参数令左图的组边界分别位于31、39、47 等;右图中,对origin 参数增加4,令组边界分别位于35、43、51 等:
h <- ggplot(faithful, aes(x=waiting)) # 将基本绘图结果存为变量以便于重复使用
h + geom_histogram(binwidth=8, fill="white", colour="black", origin=31)
h + geom_histogram(binwidth=8, fill="white", colour="black", origin=35)
两图对应的分组数目相同,但绘图结果差异很大。本例中的的faithful 数据集共包含272 个观测值,数据量并不算少;当数据量较小时,对分组边界的影响将会更大。因此,绘制图形时,最好尝试一下不同的分组数目和分组边界。
当数据集包含离散型数据时,直方图的非对称性不可忽视。数据分组时,各分组区间左闭右开。比如,当分组边界为1、2、3 等时,对应的分组区间为[1,2)、[2,3)、[3,4)等。换言之,第一个分组区间包含1,但不包含2,第二个分组区间包含2,但不包含3。
运行代码geom_bar(stat="bin") 也能得到相同的结果,不过,geom_histogram() 函
数的操作过程更易于解释。
另见
绘制多个数据对应的分布时,频数多边形(frequency polygon)是一个更佳的方案,因为,它避免了各个条形之间相互干扰。相关内容参见6.5 节。
基于分组数据绘制分组直方图
问题
如何绘制多组数据的直方图?
方法
运行geom_histogram() 函数并使用分面绘图即可,如图6-4 所示:
library(MASS) # 为了使用数据
# 使用smoke 作为分面变量
ggplot(birthwt, aes(x=bwt)) + geom_histogram(fill="white",colour="black")+
facet_grid(smoke ~ .)
讨论
绘制上图时,要求所有用到的数据都包含在一个数据框里,且数据框其中一列是可用于分组的分类变量。
这里以birthwt 数据集为例。该数据集包含的是关于婴儿出生体重及一系列导致出生体重过低的危险因子的数据:
birthwt
low age lwt race smoke ptl ht ui ftv bwt
0 19 182 2 0 0 0 1 0 2523
0 33 155 3 0 0 0 0 3 2551
0 20 105 1 1 0 0 0 1 2557
...
分面绘图有一个问题,即分面标签只有0 和1,且没有指明这个标签是变量smoke 的取值。想要修改标签,我们需要修改因子水平的名称。首先列出现有的因子水平,然后,依照相同的顺序向它们赋予新的名字:
birthwt1 <- birthwt # 复制一个数据副本
# 将smoke 转化为因子
birthwt1$smoke <- factor(birthwt1$smoke)
levels(birthwt1$smoke)
"0""1"
library(plyr) # 为了使用revalue() 函数
birthwt1$smoke <- revalue(birthwt1$smoke, c("0"="No Smoke", "1"="Smoke")
重新绘图,图形中为新的分面标签(见图6-4 右图)。
ggplot(birthwt1, aes(x=bwt)) + geom_histogram(fill="white", colour="black") +
facet_grid(smoke ~ .)
分面绘图时,各分面对应的y 轴标度是相同的。当各组数据包含的样本数目不同时,可能会难以比较各组数据的分布形状。我们可以看看按照race 对出生体重进行分组并分面绘图的结果(见图6-5 左图):
ggplot(birthwt, aes(x=bwt)) + geom_histogram(fill="white", colour="black") +
facet_grid(race ~ .)
设置参数scales="free" 可以单独设定各个分面的y 轴标度。注意:这种设置只适用于y 轴标度,x 轴的标度仍是固定的,因为各个分面的直方图是依照x 轴进行对齐的。
ggplot(birthwt, aes(x=bwt)) + geom_histogram(fill="white", colour="black") +
facet_grid(race ~ ., scales="free")
分组绘图的另一种做法是把分组变量映射给fill,如图6-6 所示。此处的分组变量必须是因子型或者字符型的向量。对于birthwt 数据集,变量smoke 是合适的分组变量,由于其被存储为数值型,所以,我们使用前面创建的birthwt1 数据集,该数据集中的smoke 变量是因子型变量:
# 把smoke 转化为因子