ggplot2作图详解6:标尺(scale)设置

评论15,809

标尺是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')

ggplot2作图详解6:标尺(scale)设置-图片1ggplot2作图详解6:标尺(scale)设置-图片2

颜色可以使用预设颜色名称,也可以使用十六进制表示。颜色空间可以是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')

ggplot2作图详解6:标尺(scale)设置-图片3ggplot2作图详解6:标尺(scale)设置-图片4

连续填充色设置函数还有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)

ggplot2作图详解6:标尺(scale)设置-图片5ggplot2作图详解6:标尺(scale)设置-图片6

而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))

ggplot2作图详解6:标尺(scale)设置-图片7ggplot2作图详解6:标尺(scale)设置-图片8

注意参数名称为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)

ggplot2作图详解6:标尺(scale)设置-图片9ggplot2作图详解6:标尺(scale)设置-图片10

注意:因为映射是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))

ggplot2作图详解6:标尺(scale)设置-图片11ggplot2作图详解6:标尺(scale)设置-图片12

 

grey灰度标尺函数是设置离散型颜色的另外一类函数,用法很简单。

p + geom_point() + scale_color_grey(start = 0, end = 0.8)

ggplot2作图详解6:标尺(scale)设置-图片13

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")

ggplot2作图详解6:标尺(scale)设置-图片14ggplot2作图详解6:标尺(scale)设置-图片15

与其去记那些调色板名称,还不如用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()

ggplot2作图详解6:标尺(scale)设置-图片16ggplot2作图详解6:标尺(scale)设置-图片17

设置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)

ggplot2作图详解6:标尺(scale)设置-图片18ggplot2作图详解6:标尺(scale)设置-图片19

如果xy轴都是非因子数据,limits的设置比较顺利,但另外一个坐标轴还不能自动调整,可能需要改进:

p + scale_x_continuous(limits=c(0.5,1.5))
p + scale_y_continuous(limits=c(500,1000))

ggplot2作图详解6:标尺(scale)设置-图片20ggplot2作图详解6:标尺(scale)设置-图片21

用limits参数设置因子型数据轴还有意外的效果:既能选择要显示的数据子集,还能调整它们在图形上的显示顺序:

qplot(x=x, y=y, geom='bar') + scale_x_discrete(limits=c('W', 'D', 'F'))

ggplot2作图详解6:标尺(scale)设置-图片22

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()")

ggplot2作图详解6:标尺(scale)设置-图片23ggplot2作图详解6:标尺(scale)设置-图片24

同样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")

ggplot2作图详解6:标尺(scale)设置-图片25ggplot2作图详解6:标尺(scale)设置-图片26

 

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()

ggplot2作图详解6:标尺(scale)设置-图片27ggplot2作图详解6:标尺(scale)设置-图片28

第一个图没改变坐标轴标尺,所以两个拟合直线是完全重合的;而第二个图中两条先就差别很大,原来红色的直线变成了曲线,而geom_smooth获得的仍然是直线。改变坐标轴范围也是同样的效果:

p + gs1 + gs2 + scale_y_continuous(limits=c(1000,10000))
p + gs1 + gs2 + ylim(limits=c(1000,10000))

ggplot2作图详解6:标尺(scale)设置-图片29ggplot2作图详解6:标尺(scale)设置-图片30

也就是说人工设置坐标轴标尺后改变了用于建立映射的数据,或作变换,或取子集(设置limits),这个过程发生在建立映射之前。如果想在ggplot2建立映射后改变坐标轴,应该用coord_xxx类型函数:

p + gs1 + gs2 + coord_cartesian(ylim=c(1000,10000))
p + gs1 + gs2 + coord_trans(xtrans='log10')

ggplot2作图详解6:标尺(scale)设置-图片31ggplot2作图详解6:标尺(scale)设置-图片32

前面用到了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))

ggplot2作图详解6:标尺(scale)设置-图片33ggplot2作图详解6:标尺(scale)设置-图片34

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')

ggplot2作图详解6:标尺(scale)设置-图片35ggplot2作图详解6:标尺(scale)设置-图片36

 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

发表评论

匿名网友