标尺是ggplot2作图必需的元素,在《映射》一节提到了它的概念并简单进行了设置。在数据分析阶段,为避免陷入数据无关的垃圾坑,我们只需要设置映射,ggplot2自动配置合适的标尺并产生坐标和图例。这是ggplot2适合数据可视化分析的原因之一。
在图形美化阶段,我们可以通过修改标尺改善图形外观。标尺设置一般不会对数据产生影响,但坐标轴标尺除外。
1 标尺设定函数
ggplot2修改标尺的函数有一大堆:
library(ggplot2) scalex <- ls("package:ggplot2", pattern="^scale.+") length(scalex) ## [1] 66
提取函数名的第二个字段,对这些函数的作用进行分类:
scalex <- scalex[grep("([^_]+_){2}.+", scalex)] unique(gsub("(([^_]+_){2}).+","\\1***",scalex)) ## [1] "scale_alpha_***" "scale_color_***" "scale_colour_***" ## [4] "scale_fill_***" "scale_linetype_***" "scale_shape_***" ## [7] "scale_size_***" "scale_x_***" "scale_y_***"
可以看到标尺设置的内容有8种(颜色color/colour算一种):线条颜色、填充色、透明度、线型、形状、大小,x和y轴。标尺设置的内容都有对应的映射设置类型,但映射比标尺多了xmin, xmax, ymin, ymax, xend, yend,group和string等(请参看《映射》一节)。
虽然设置函数很多,但不管是函数用法还是函数名称上都是很有规律的:
# 线条颜色 scalexx <- scalex[grepl("scale_color.+", scalex)] unique(gsub("(([^_]+_){2})(.+)","\\3",scalexx)) ## [1] "brewer" "continuous" "discrete" "gradient" "gradient2" ## [6] "gradientn" "grey" "hue" "identity" "manual" # 填充色 scalexx <- scalex[grepl("scale_fill.+", scalex)] unique(gsub("(([^_]+_){2})(.+)","\\3",scalexx)) ## [1] "brewer" "continuous" "discrete" "gradient" "gradient2" ## [6] "gradientn" "grey" "hue" "identity" "manual" # 大小 scalexx <- scalex[grepl("scale_size.+", scalex)] unique(gsub("(([^_]+_){2})(.+)","\\3",scalexx)) ## [1] "area" "continuous" "discrete" "identity" "manual" # 透明度 scalexx <- scalex[grepl("scale_alpha.+", scalex)] unique(gsub("(([^_]+_){2})(.+)","\\3",scalexx)) ## [1] "continuous" "discrete" "identity" "manual" # 线型 scalexx <- scalex[grepl("scale_linetype.+", scalex)] unique(gsub("(([^_]+_){2})(.+)","\\3",scalexx)) ## [1] "continuous" "discrete" "identity" "manual" # 形状 scalexx <- scalex[grepl("scale_shape.+", scalex)] unique(gsub("(([^_]+_){2})(.+)","\\3",scalexx)) ## [1] "continuous" "discrete" "identity" "manual" # x轴 scalexx <- scalex[grepl("scale_x.+", scalex)] unique(gsub("(([^_]+_){2})(.+)","\\3",scalexx)) ## [1] "continuous" "date" "datetime" "discrete" "log10" ## [6] "reverse" "sqrt" # y轴 scalexx <- scalex[grepl("scale_y.+", scalex)] unique(gsub("(([^_]+_){2})(.+)","\\3",scalexx)) ## [1] "continuous" "date" "datetime" "discrete" "log10" ## [6] "reverse" "sqrt"
除坐标轴外,其它标尺都有四种基本设置函数:"continuous","discrete","identity"和"manual"。结合标尺的作用和设定方法两个标准,H.W把它们分为4种类型的标尺:位置、颜色、无变换和人工设置类型(说实话,他的分类思维有点乱)。颜色设置相关的函数较多,线条颜色和填充色设置的函数类型一样,而x轴和y轴设置的函数类型也一样。
由于标尺函数的命名和用法很有规律,下面仅介绍颜色和坐标轴设置函数的一些用法。
2 颜色标尺设置
2.1 连续型颜色标尺
ggplot2提供了10个填充色设置的标尺函数(线条颜色也一样):
ls("package:ggplot2", pattern="^scale_fill.+") ## [1] "scale_fill_brewer" "scale_fill_continuous" ## [3] "scale_fill_discrete" "scale_fill_gradient" ## [5] "scale_fill_gradient2" "scale_fill_gradientn" ## [7] "scale_fill_grey" "scale_fill_hue" ## [9] "scale_fill_identity" "scale_fill_manual"
先看看“continuous”的用法。对于数据为非因子型的填充色映射,ggplot2自动使用“continuous”类型颜色标尺表示连续颜色空间。如果要修改默认颜色就要使用scale_fill_continuous函数进行修改,这个函数最有用的参数是low和high,分别表示低端和高端数据的颜色,中间颜色根据颜色空间space自动计算:
theme_set(theme_bw()) df <- expand.grid(1:30, 1:30) colnames(df) <- c('x','y') df$z <- rnorm(900) p <- ggplot(data=df, aes(x=x, y=y, fill=z)) p + geom_raster() p + geom_raster() + scale_fill_continuous(low="darkgreen", high="orangered", space='rgb')
颜色可以使用预设颜色名称,也可以使用十六进制表示。颜色空间可以是rgb或Lab,两者差别还比较大:
p + geom_raster() + scale_fill_continuous(low="#000099", high="#FF0000", space='rgb') p + geom_raster() + scale_fill_continuous(low="#000099", high="#FF0000", space='Lab')
连续填充色设置函数还有scale_fill_gradient,scale_fill_gradient2和scale_fill_gradientn,其中scale_fill_gradient的用法和作用和scale_fill_continuous完全相同(其实ggplot2早期版本连续颜色标尺默认使用scale_fill_gradient,没有scale_fill_continuous函数;后者可能是H.W头脑清楚以后加进去的,相当于前者的别名)。scale_fill_gradient2增加了中间点和中间颜色的设置,效果相当不错:
p + geom_raster() + scale_fill_gradient2(low="darkgreen", high="red", mid="yellow") p + geom_raster() + scale_fill_gradient2(low="darkgreen", high="red", mid="yellow", midpoint=1)
而scale_fill_gradientn可以使用colours参数设置多个中间颜色,配合其它颜色参数函数使用也很不错:
p + geom_raster() + scale_fill_gradientn(colours=c("blue","green","yellow","red")) p + geom_raster() + scale_fill_gradientn(colours=terrain.colors(100))
注意参数名称为colours,不是colors,美人们可能不习惯,不过问题不大。
2.2 离散(间断)型颜色标尺
如果数据是因子型的颜色映射,颜色标尺则是离散型的,修改标尺需要使用相应的离散型颜色标尺如scale_color_discrete或scale_color_hue。这两个函数只是别名函数,早期版本只有scale_color_hue。它们通过设置色调范围(h)、饱和度(c)和亮度(l)获取颜色,不太容易掌握:
set.seed(100) dms <- diamonds[sample(nrow(diamonds),500),] p <- ggplot(data=dms, aes(x=carat, y=price, color=cut)) p + geom_point() + scale_color_discrete() p + geom_point() + scale_color_discrete(h=c(150,350), c=100, l=60)
注意:因为映射是color,所以标尺设置也得相应用scale_color而不是scale_fill。
scale_color_discrete或scale_color_hue设置颜色不是很直观,如果想要啥来啥,那就用manual类型函数:
p + geom_point() + scale_color_manual(values=c('blue','cyan', 'yellow', 'orange', 'red')) p + geom_point() + scale_color_manual(values=rainbow(5))
grey灰度标尺函数是设置离散型颜色的另外一类函数,用法很简单。
p + geom_point() + scale_color_grey(start = 0, end = 0.8)
brewer类型函数则可以直接使用RColorBrewer包预定义的一些调色板,那些调色板最多能设置8-11种颜色不等,如果超过最大颜色数就不合适了。
x <- sample(LETTERS,13); y <- 1:13 qplot(x=x, y=y, fill= x, geom='bar') + scale_fill_brewer(palette="YlOrRd") x <- x[1:8]; y=y[1:8] qplot(x=x, y=y, fill= x, geom='bar') + scale_fill_brewer(palette="YlOrRd")
与其去记那些调色板名称,还不如用manual可以设置自己需要的颜色(可参考本博客的文章《R语言进阶之一:颜色设置》)。
查看scale_fill_gradientn等函数的说明发现很多用于连续颜色设置的函数都有palette参数选项,似乎连续型和离散型颜色在函数上没有严格区别,但实际使用时会出错,或许这些功能只是H.W做的TODO list。
2.3 identity标尺
如果数据本身就是可以用作标尺的取值,那当然可以直接使用:
set.seed(2) (col <- sample(colors(),4)) ## [1] "deepskyblue1" "mediumblue" "indianred4" "darkslategray2" val <- abs(rnorm(4))*10 qplot(x=col, y=val, fill= col, geom='bar') + scale_fill_identity() qplot(x=carat, y=price, data=dms, size=x) + scale_size_identity()
设置identity标尺后不再产生对应的图例。
3 坐标轴标尺设置
ggplot2为x或y轴标尺的设置分别提供了7个函数:
ls("package:ggplot2", pattern="^scale_x.+") ## [1] "scale_x_continuous" "scale_x_date" "scale_x_datetime" ## [4] "scale_x_discrete" "scale_x_log10" "scale_x_reverse" ## [7] "scale_x_sqrt"
这些函数最基本的是continuous和discrete两个,通过设置它们的参数可以实现其它函数的效果。
3.1 breaks, labels, limits参数
continuous和discrete坐标轴标尺设定函数中最常用的参数是breaks、labels和limits,分别用于设置刻度位置、刻度标签和坐标轴范围。先看看前两个参数:
p <- ggplot(data=dms, aes(x=carat, y=price)) + geom_point() bks <- pretty(range(dms$price), 10) p + scale_y_continuous(breaks=bks) bks <- c(0, 2000, 10000, 15500, 18000) p + scale_y_continuous("Price (*1000)", breaks=bks, labels=bks/1000)
如果xy轴都是非因子数据,limits的设置比较顺利,但另外一个坐标轴还不能自动调整,可能需要改进:
p + scale_x_continuous(limits=c(0.5,1.5)) p + scale_y_continuous(limits=c(500,1000))
用limits参数设置因子型数据轴还有意外的效果:既能选择要显示的数据子集,还能调整它们在图形上的显示顺序:
qplot(x=x, y=y, geom='bar') + scale_x_discrete(limits=c('W', 'D', 'F'))
3.2 trans参数
连续数据的坐标轴可以设置trans参数,它应该是通过调用scales包的相应trans类型实现的,比如scales中有log10_trans,ggplot2中可以直接设置trans='log10',它其实就是scale_x_log10函数的效果:
p + scale_y_continuous(trans='log10') + ggtitle("scale_y_continuous(trans='log10')") p + scale_y_log10() + ggtitle("scale_y_log10()")
同样reverse_trans和sqrt_trans也等价于scale_x_reverse和scale_x_sqrt,它们分别对坐标轴反转和求平方根。日期相关的转换函数scale_x_date和scale_x_datetime我没用过,就不说来。scales包中还有其它一些转换函数,但在ggplot中没有对应的设置函数,如果数据合适,有些可以直接用:
p + scale_y_continuous(trans='reciprocal') + ggtitle("reciprocal_trans") p + scale_x_continuous(trans='log1p') + ggtitle("log1p_trans")
3.3 坐标轴标尺转换与数据映射
如果你认为坐标轴标尺只是改变了坐标轴的外观那就错了,它还影响到用于建立映射的数据。下面我们分别用坐标轴标尺应用之前和之后的数据获得拟合直线:
lmx <- glm(price~carat, data=dms) gs1 <- geom_line(aes(y=lmx$fitted.values), size=3, color='red') gs2 <- geom_smooth(aes(group=1), method="lm", se=FALSE, size=1.5) p + gs1 + gs2 p + gs1 + gs2 + scale_x_log10()
第一个图没改变坐标轴标尺,所以两个拟合直线是完全重合的;而第二个图中两条先就差别很大,原来红色的直线变成了曲线,而geom_smooth获得的仍然是直线。改变坐标轴范围也是同样的效果:
p + gs1 + gs2 + scale_y_continuous(limits=c(1000,10000)) p + gs1 + gs2 + ylim(limits=c(1000,10000))
也就是说人工设置坐标轴标尺后改变了用于建立映射的数据,或作变换,或取子集(设置limits),这个过程发生在建立映射之前。如果想在ggplot2建立映射后改变坐标轴,应该用coord_xxx类型函数:
p + gs1 + gs2 + coord_cartesian(ylim=c(1000,10000)) p + gs1 + gs2 + coord_trans(xtrans='log10')
前面用到了ylim函数,同样也有xlim,它们只是辅助函数,实质调用了坐标轴标尺设置函数。在本系列《映射》一文我们还提到柱形图不能用scale类函数调整坐标轴刻度范围,主要原因是:柱形图即直方图,不能改变y轴起始为非0;另外scale设置导致取数据子集,随之直方图坐标轴范围改变,这些改变多数情况下会和scale的设置冲突。用scale设置柱形图保险不出错的情况是设置的范围比数据范围要大,但没有什么实际意义:
qplot(x=x, y=y, geom='bar') qplot(x=x, y=y, geom='bar') + ylim(limits=c(-10,10))
4 标尺函数的通用参数
除前面提到的breaks和labels外,常用的还有name,用于改变所设scale的名称,具体表现是改变坐标轴标题或图例标题。放在第一个参数的位置可以不用写参数名称。
qplot(x=carat, y=price, color=cut, data=dms) + scale_color_hue('Diamond Cut') qplot(x=carat, y=price, color=cut, data=dms) + scale_y_continuous('Diamond Cut')
5 SessionInfo
sessionInfo() ## R version 3.1.0 (2014-04-10) ## Platform: x86_64-pc-linux-gnu (64-bit) ## ## locale: ## [1] LC_CTYPE=zh_CN.UTF-8 LC_NUMERIC=C ## [3] LC_TIME=zh_CN.UTF-8 LC_COLLATE=zh_CN.UTF-8 ## [5] LC_MONETARY=zh_CN.UTF-8 LC_MESSAGES=zh_CN.UTF-8 ## [7] LC_PAPER=zh_CN.UTF-8 LC_NAME=C ## [9] LC_ADDRESS=C LC_TELEPHONE=C ## [11] LC_MEASUREMENT=zh_CN.UTF-8 LC_IDENTIFICATION=C ## ## attached base packages: ## [1] tcltk stats graphics grDevices utils datasets methods ## [8] base ## ## other attached packages: ## [1] ggplot2_0.9.3.1 zblog_0.1.0 knitr_1.5 ## ## loaded via a namespace (and not attached): ## [1] colorspace_1.2-4 digest_0.6.4 evaluate_0.5.3 ## [4] formatR_0.10 grid_3.1.0 gtable_0.1.2 ## [7] highr_0.3 labeling_0.2 MASS_7.3-31 ## [10] munsell_0.4.2 plyr_1.8.1 proto_0.3-10 ## [13] RColorBrewer_1.0-5 Rcpp_0.11.1 reshape2_1.2.2 ## [16] scales_0.2.4 stringr_0.6.2 tools_3.1.0
原文来自:http://blog.csdn.net/u014801157/article/details/24372521