ggplot2作图详解3:映射(mapping)

作图前的数据准备工作不仅仅指原始数据的收集,还包括数据外观的整理,这些工作对后续的作图无疑十分重要。和其他作图方法相比,ggplot2的优点之一就是把数据整理融合到了作图过程中,替用户分担了数据整型的部分工作。ggplot2数据层面的操作包括映射和分面。先说映射。

1 映射的类型

前面我们已经了解到ggplot对象的data项存储了整个数据框的内容,而“映射”则确定如何使用这些数据。

ggplot2按照图形属性提供了以下可用映射类型:

  • 颜色类型映射:包括 color(颜色或边框颜色)、fill(填充颜色)和 alpha(透明度)
  • 形状类型映射:包括 linetype(线型)、size(点的大小或线的宽度)和 shape(形状)
  • 位置类型映射:包括 x, y, xmin, xmax, ymin, ymax, xend, yend
  • 特殊类型:包括两类,一类是指定数据分组和顺序的映射group和order,另一类是字符串映射。

前两种类型是经典的美学属性映射,第三类的x和y映射也常规,第四类很特别,尤其是字符串映射,很另类,其他类型的映射都可以用aes函数指定,但H.W.为字符串映射专门造了个函数:aes_string。不知道他对字符串特别关照还是实在想不出其他解决方案。

2 颜色和形状类型映射

规律性的东西简单轻松,大家都喜欢;而到处暗藏潜规则、充斥着特例的东西(比如plotrix、perl和中国社会)很杂碎很累人,当然也很让人烦躁和讨厌。ggplot2中颜色和形状这两类映射最符合台面规则的,即:把数据框的变量和图形的美学属性对应起来。

2.1 映射的过程

先看下面ggplot2的数据diamonds:

  1. library(ggplot2)
  2. set.seed(100)
  3. d.sub <- diamonds[sample(nrow(diamonds), 500), ]
  4. head(d.sub, 4)
  5. ## carat cut color clarity depth table price x y z
  6. ## 16601 1.01 Very Good D SI1 62.1 59 6630 6.37 6.41 3.97
  7. ## 13899 0.90 Ideal D SI1 62.4 55 5656 6.15 6.19 3.85
  8. ## 29792 0.30 Ideal D SI1 61.6 56 709 4.34 4.30 2.66
  9. ## 3042 0.30 Very Good G VS1 62.0 60 565 4.27 4.31 2.66

作图首先要指定x和y数据,即建立数据框变量和x/y之间的映射:

  1. p <- ggplot(data=d.sub, aes(x=carat, y=price))

作出散点图:

  1. theme_set(theme_bw())
  2. p + geom_point()

ggplot2作图详解3:映射(mapping)-图片1

如果还要建立其他映射,比如用钻石颜色(color)分类数据确定点的颜色,图形外观就会发生变化(为方便说明,先去掉图例):

  1. p + geom_point() + aes(color=color) + theme(legend.position=c(2,2))
ggplot2作图详解3:映射(mapping)-图片2

 

ggplot2映射的过程可以用plot函数作图步骤进行分解,它包含三方面的操作(不包括图形页面设置):

  • 数据分组
  • 设定颜色标尺
  • 按颜色标尺指定每组数据的颜色
  1. # 设定颜色标尺
  2. levs <- levels(d.sub$color)
  3. cl <- rainbow(length(levs))
  4. # 页面设置
  5. par(mar=c(3,3,0.5,0.5), mgp=c(1.5, 0.5, 0), bg="white")
  6. plot(d.sub$carat, d.sub$price, type='n', xlab="carat", ylab="price")
  7. i <- 1
  8. for(lev in levs){
  9. # 数据分组
  10. datax <- d.sub[d.sub$color==lev, ]
  11. # 作图并指定数据点颜色
  12. points(datax$carat, datax$price, pch=20, col=cl[i])
  13. i <- i + 1
  14. }

ggplot2作图详解3:映射(mapping)-图片3

上面对数据的分组只设定了一个变量,如果增加数据分组的变量,ggplot2中只需要增加映射的类型就可以了,比如在颜色分类的基础上加钻石切工(cut)进行分类:

  1. p + geom_point() + aes(color=color, shape=cut) + theme(legend.position=c(2,2))

ggplot2作图详解3:映射(mapping)-图片4

用plot函数处理起来要考虑的问题就多一些,可以自己试试。

2.2 映射的标尺

用plot函数作图我们得自己考虑使用什么颜色表示不同组的数据,也就是使用什么标尺(或比例尺)。ggplot2则自动应用标尺,这是一个隐含过程。标尺大体可以分为两类:

  • 离散型(或枚举型)标尺。罗列出所有数据分类并将其与美学属性一一对应,处理过程包含数据分类,如上例。
  • 连续型(或区间型)标尺。看下面例子:
  1. p + geom_point() + aes(size= x*y*z ) + theme(legend.position=c(2,2))

ggplot2作图详解3:映射(mapping)-图片5

上图中点的大小反映钻石的x*y*z值,相当于钻石的大小。用plot函数也可以实现:

  1. cex <- d.sub[,"x"]*d.sub[,"y"]*d.sub[,"z"]
  2. cex <- cex/max(cex)*4
  3. par(mar=c(3,3,0.5,0.5), mgp=c(1.5, 0.5, 0), bg="white")
  4. plot(d.sub$carat, d.sub$price, type='n', xlab="carat", ylab="price")
  5. points(d.sub[, "carat"], d.sub[, "price"], pch=20, cex=cex)

ggplot2作图详解3:映射(mapping)-图片6

可以看到作图过程也需要手动建立数据和图形属性间的对应关系,但没有对数据分类。

ggplot2对映射应用的标尺可以修改,ggplot提供了一大批 scale_xxxxxxxx 类型的函数,比如 scale_color_xxxx 类型函数用户修改颜色标尺,scale_shape_xxxx 修改形状,scale_linetype_xxxx 修改线型等。按照数据的类型,这些函数还有4种基本类型:

  • continuous:连续型
  • discrete:离散型
  • identity:和数据取值相同
  • manual:手工指定

有关颜色和坐标轴标尺设定的函数较多,适应不同需要。

  1. cls <- terrain.colors(length(levels(d.sub$color)))
  2. p + geom_point() + aes(color=color) + scale_color_manual(values=cls)

ggplot2作图详解3:映射(mapping)-图片7

 

2.3 映射与图例

映射还有一个作用:产生图例。这在ggplot2也是自动的隐含过程,但在plot函数作图中是一个体力活,制作过程就不举例说明了,可以参考legend函数。

2.4 图形颜色和形状的非映射设置

除了通过映射设置几何图形的图形颜色和形状属性外,ggplot2还提供了直接设定方式。和映射方式设置不一样的是:直接设定方式不会在图例上有反映。比较下面两图:

  1. p + geom_boxplot(aes(x=cut, fill=cut)) +
  2. scale_fill_manual(values=rep("cyan", length(levels(d.sub$cut))))
  3. p + geom_boxplot(aes(x=cut), fill="cyan")

ggplot2作图详解3:映射(mapping)-图片8ggplot2作图详解3:映射(mapping)-图片8

虽然填充色都是青色,但前者用的映射对数据进行了分组,所以会出现分组图例。注意:直接设定方法的参数名称和映射设定是一样的,但是不放在aes函数内部。

在qplot函数中如果要进行美学属性的非映射设定得用 “I” 函数,否则将被当长映射设置。

  1. qplot(x=cut, y=price, data=d.sub, geom="boxplot", fill="cyan")
  2. qplot(x=cut, y=price, data=d.sub, geom="boxplot", fill=I("cyan"))
ggplot2作图详解3:映射(mapping)-图片9ggplot2作图详解3:映射(mapping)-图片9

“I”函数表示设为固定值,如果不是在qplot函数中可以不用它。

透明度属性虽然包含在映射类型中,但一般情况下都是直接设定而非映射设定:

  1. p + geom_point(data=diamonds, aes(alpha=carat/100))
  2. p + geom_point(data=diamonds, alpha=0.05)
ggplot2作图详解3:映射(mapping)-图片10ggplot2作图详解3:映射(mapping)-图片10

第一张图就达不到设置透明度显示点密集度的效果

3 位置类型映射

x和y映射的用法很明确,就不再罗嗦了。xmin, xmax, ymin, ymax, xend, yend这几种映射属于特殊类型,H.W.在ggplot2的说明档里面写得很清楚(赞,H.W.不仅是写R软件的高手,还是普及教育的牛人),下面就照搬他的例子简单说明一下用法。

3.1 ymin/ymax映射的用法

下面代码通过直线拟合产生了钻石切工和价格的关系数据(预测的价格和标准差)

  1. dmod <- lm(price ~ cut, data = diamonds)
  2. cuts <- data.frame(cut = unique(diamonds$cut), predict(dmod, data.frame(cut =
  3. unique(diamonds$cut)), se = TRUE)[c 1=""se.fit")" language="("fit","][/c])
  4. cuts
  5. ## cut fit se.fit
  6. ## 1 Ideal 3458 27.00
  7. ## 2 Premium 4584 33.75
  8. ## 3 Good 3929 56.59
  9. ## 4 Very Good 3982 36.06
  10. ## 5 Fair 4359 98.79

通过设定ymin/ymax映射,用pointrange几何类型可以直接做出带误差线的散点图,无需使用errorbar设置:

  1. se <- ggplot(cuts, aes(x = cut, y = fit, ymin = fit - se.fit, ymax = fit + se.fit, colour = cut))
  2. se + geom_pointrange()

ggplot2作图详解3:映射(mapping)-图片11

当然也可以先画点再做误差线,这样思路明确些。或者做其他类型的图如柱形图:

  1. se + geom_point() + geom_errorbar(width=0.2)
  2. se + geom_bar(stat="identity", aes(fill=cut)) + geom_errorbar(width=0.2)

ggplot2作图详解3:映射(mapping)-图片12ggplot2作图详解3:映射(mapping)-图片12

min/ymax可以用来改变几何类型的坐标轴范围,但 这不是标准用法 ,最简单的是用ylim函数:

  1. se + geom_point(aes(ymin = 3000, ymax = 4800)) + geom_errorbar(width=0.2)
  2. se + geom_point() + geom_errorbar(width=0.2) + ylim(3000,4800)
  3. # 或者用: scale_y_continuous(limits=c(3000,5000))

ggplot2作图详解3:映射(mapping)-图片13ggplot2作图详解3:映射(mapping)-图片13

但以上方法都不适用于柱形图,得用下面的方法,具体原因以后章节再说:

  1. se + geom_bar(stat="identity", aes(fill=cut)) +
  2. geom_errorbar(width=0.2) + coord_cartesian(ylim=c(3000,4800))
ggplot2作图详解3:映射(mapping)-图片14

如果几何类型的设置参数中就包含位置类型映射,情况是很不一样的。所谓“太极”,有点道理:

  1. px <- ggplot(mtcars, aes(wt, mpg)) + geom_point()
  2. px + annotate("rect", xmin = 2, xmax = 3.5, ymin = 2, ymax = 25, fill = "dark grey", alpha = .5)
  3. library(grid)
  4. px + geom_segment(aes(x = 5, y = 30, xend = 3.5, yend = 25), arrow = arrow(length = unit(0.5, "cm")))

ggplot2作图详解3:映射(mapping)-图片15ggplot2作图详解3:映射(mapping)-图片15

4 特殊类型映射

在ggplot2作图过程中,映射的处理在先于其他绘图步骤,也先于统计运算。颜色和形状类型的映射会对数据进行分组,统计运算使用的也是分组后的数据:

  1. ggplot(d.sub, aes(x=carat, y=price, color=cut)) +
  2. geom_point() + geom_smooth(method="lm", se=FALSE)

ggplot2作图详解3:映射(mapping)-图片16

上面图中平滑曲线的统计处理是按cut进行分类后的数据进行的,分别作出了每一类数据的曲线。但如果要按分组前的数据做统计,就得把数据设为一个整体组;如果要按其他分组方式进行统计,也可以灵活设置:

  1. ggplot(d.sub, aes(x=carat, y=price, color=cut)) +
  2. geom_point() + geom_smooth(aes(group=1), method="lm", se=FALSE)
  3. ggplot(d.sub, aes(x=carat, y=price, color=cut)) + geom_point() +
  4. geom_smooth(aes(group=color, linetype=color), method="lm", se=FALSE, color="black")
ggplot2作图详解3:映射(mapping)-图片17ggplot2作图详解3:映射(mapping)-图片17

特殊类型映射有特殊应用。曲线图和柱形图对于x轴数据类型的要求是不一样的,曲线图要用连续型数据,而柱形图要用因子型(或离散型)数据,这两类图形如果不经特殊处理就不能放在一起。group映射可以轻松搞定它:

  1. se + geom_bar(stat="identity", aes(fill=cut)) + geom_errorbar(width=0.2) +
  2. coord_cartesian(ylim=c(3000,4800)) + geom_line(aes(group=1), color="black")
20140426082544843

order映射用于改变数据类型的排序。注意是在图层中的排列顺序而不是图例的先后顺序。看下面图形颜色的差别:

  1. p + geom_point(aes(color=cut, order=cut))
  2. library(plyr) # 使用desc函数
  3. p + geom_point(aes(color=cut, order=desc(cut)))

ggplot2作图详解3:映射(mapping)-图片18ggplot2作图详解3:映射(mapping)-图片18

aes_string太过另类,不说了。

5 SessionInfo

  1. sessionInfo()
  2. ## R version 3.1.0 (2014-04-10)
  3. ## Platform: x86_64-pc-linux-gnu (64-bit)
  4. ##
  5. ## locale:
  6. ## [1] LC_CTYPE=zh_CN.UTF-8 LC_NUMERIC=C
  7. ## [3] LC_TIME=zh_CN.UTF-8 LC_COLLATE=zh_CN.UTF-8
  8. ## [5] LC_MONETARY=zh_CN.UTF-8 LC_MESSAGES=zh_CN.UTF-8
  9. ## [7] LC_PAPER=zh_CN.UTF-8 LC_NAME=C
  10. ## [9] LC_ADDRESS=C LC_TELEPHONE=C
  11. ## [11] LC_MEASUREMENT=zh_CN.UTF-8 LC_IDENTIFICATION=C
  12. ##
  13. ## attached base packages:
  14. ## [1] grid tcltk stats graphics grDevices utils datasets
  15. ## [8] methods base
  16. ##
  17. ## other attached packages:
  18. ## [1] plyr_1.8.1 ggplot2_0.9.3.1 zblog_0.1.0 knitr_1.5
  19. ##
  20. ## loaded via a namespace (and not attached):
  21. ## [1] colorspace_1.2-4 digest_0.6.4 evaluate_0.5.3 formatR_0.10
  22. ## [5] gtable_0.1.2 highr_0.3 labeling_0.2 MASS_7.3-31
  23. ## [9] munsell_0.4.2 proto_0.3-10 Rcpp_0.11.1 reshape2_1.2.2
  24. ## [13] scales_0.2.4 stringr_0.6.2 tools_3.1.0

原文来自:http://blog.csdn.net/u014801157/article/details/24372505

发表评论

匿名网友

拖动滑块以完成验证
加载失败