ggplot2基本要素
这里将从这些基本要素对ggplot2进行介绍。 数据和映射下面以一份钻石的数据为例,这份数据非常大,随机取一个子集来画图。 require(ggplot2)data(diamonds)set.seed(42)small <- diamonds[sample(nrow(diamonds),="">->1000), ]head(small) ## carat cut color clarity depth table price x y z## 49345 0.71 Very Good H SI1 62.5 60 2096 5.68 5.75 3.57## 50545 0.79 Premium H SI1 61.8 59 2275 5.97 5.91 3.67## 15434 1.03 Ideal F SI1 62.4 57 6178 6.48 6.44 4.03## 44792 0.50 Ideal E VS2 62.2 54 1624 5.08 5.11 3.17## 34614 0.27 Ideal E VS1 61.6 56 470 4.14 4.17 2.56## 27998 0.30 Premium E VS2 61.7 58 658 4.32 4.34 2.67 画图实际上是把数据中的变量映射到图形属性上。以克拉数为X轴变量,价格为Y轴变量。 p <- ggplot(data="small," mapping="aes(x" =="" carat,="" y="">-> 上面这行代码把数据映射XY坐标轴上,需要告诉ggplot2,这些数据要映射成什么样的几何对象,下面以散点为例: p + geom_point() 几何对象将在下面的小节介绍,这一节,关注的是数据和图形属性之间的映射。 如果想将切工(cut)映射到形状属性。只需要: p <- ggplot(data="small," mapping="aes(x=carat," y="price," shape="">-> 再比如我想将钻石的颜色(color)映射颜色属性: p <- ggplot(data="small," mapping="aes(x=carat," y="price," shape="cut," colour="">-> 几何对象(Geometric)在上面的例子中,各种属性映射由ggplot函数执行,只需要加一个图层,使用
不同的几何对象,要求的属性会有些不同,这些属性也可以在几何对象映射时提供,比如上一图,也可以用以下语法来画: p <- ggplot(small)p+geom_point(aes(x="carat," y="price," shape="cut," colour="">-> ggplot2支持图层,我通常把不同的图层中共用的映射提供给ggplot函数,而某一几何对象才需要的映射参数提供给geom_xxx函数。 这一小节我们来看一下各种常用的几何对象。 直方图 直方图最容易,提供一个x变量,画出数据的分布。 ggplot(small)+geom_histogram(aes(x=price)) 同样可以根据另外的变量给它填充颜色,比如按不同的切工: ggplot(small)+geom_histogram(aes(x=price, fill=cut)) 也可以将其分开,side-by-side地画直方图。 ggplot(small)+geom_histogram(aes(x=price, fill=cut), position='dodge') 还可以使用position=”fill”,按照相对比例来画。 ggplot(small)+geom_histogram(aes(x=price, fill=cut), position='fill') 柱状图 ggplot(small)+geom_bar(aes(x=clarity)) 柱状图两个要素,一个是分类变量,一个是数目,也就是柱子的高度。数目在这里不用提供,因为ggplot2会通过x变量计算各个分类的数目。 当然你想提供也是可以的,通过stat参数,可以让geom_bar按指定高度画图,比如以下代码: ggplot()+geom_bar(aes(x=c(LETTERS[1:3]),y=1:3), stat='identity') 柱状图和直方图是很像的,直方图把连续型的数据按照一个个等长的分区(bin)来切分,然后计数,画柱状图。而柱状图是分类数据,按类别计数。我们可以用前面直方图的参数来画side-by-side的柱状图,填充颜色或者按比例画图,它们是高度一致的。 柱状图是用来表示计数数据的,但在生物界却被经常拿来表示均值,加上误差来表示数据分布,这可以通常图层来实现,我将在图层一节中给出实例。 密度函数图 ggplot(small)+geom_density(aes(x=price, colour=cut)) ggplot(small)+geom_density(aes(x=price,fill=clarity)) colour参数指定的是曲线的颜色,而fill是往曲线下面填充颜色。 箱式图 ggplot(small)+geom_boxplot(aes(x=cut, y=price,fill=color)) geom_boxplot将数据映射到箱式图上,上面的代码,我们应该很熟悉了,按切工(cut)分类,对价格(price)变量画箱式图,再分开按照color变量填充颜色。 ggplot2提供了很多的geom_xxx函数,可以满足我们对各种图形绘制的需求。 geom_abline geom_area geom_bar geom_bin2dgeom_blank geom_boxplot geom_contour geom_crossbargeom_density geom_density2d geom_dotplot geom_errorbargeom_errorbarh geom_freqpoly geom_hex geom_histogramgeom_hline geom_jitter geom_line geom_linerangegeom_map geom_path geom_point geom_pointrangegeom_polygon geom_quantile geom_raster geom_rectgeom_ribbon geom_rug geom_segment geom_smoothgeom_step geom_text geom_tile geom_violingeom_vline 标尺(Scale)前面我们已经看到了,画图就是在做映射,不管是映射到不同的几何对象上,还是映射各种图形属性。这一小节介绍标尺,在对图形属性进行映射之后,使用标尺可以控制这些属性的显示方式,比如坐标刻度,可能通过标尺,将坐标进行对数变换;比如颜色属性,也可以通过标尺,进行改变。 ggplot(small)+geom_point(aes(x=carat, y=price, shape=cut, colour=color))+scale_y_log10()+scale_colour_manual(values=rainbow(7)) 以数据(Data)和映射(Mapping)一节中所画散点图为例,将Y轴坐标进行log10变换,再自己定义颜色为彩虹色。 统计变换(Statistics)统计变换对原始数据进行某种计算,然后在图上表示出来,例如对散点图上加一条回归线。 ggplot(small, aes(x=carat, y=price))+geom_point()+scale_y_log10()+stat_smooth() 这里就不按颜色、切工来分了,不然ggplot会按不同的分类变量分别做回归,图就很乱,如果我们需要这样做,我们可以使用分面,这个将在后面介绍。 这里,aes所提供的参数,就通过ggplot提供,而不是提供给geom_point,因为ggplot里的参数,相当于全局变量,geom_point()和stat_smooth()都知道x,y的映射,如果只提供给geom_point(),则相当于是局部变量,geom_point知道这种映射,而stat_smooth不知道,当然你再给stat_smooth也提供x,y的映射,不过共用的映射,还是提供给ggplot好。 stat_abline stat_contour stat_identity stat_summarystat_bin stat_density stat_qq stat_summary2dstat_bin2d stat_density2d stat_quantile stat_summary_hexstat_bindot stat_ecdf stat_smooth stat_uniquestat_binhex stat_function stat_spoke stat_vlinestat_boxplot stat_hline stat_sum stat_ydensity 统计变换是非常重要的功能,我们可以自己写函数,基于原始数据做某种计算,并在图上表现出来,也可以通过它改变geom_xxx函数画图的默认统计参数。 坐标系统(Coordinante)坐标系统控制坐标轴,可以进行变换,例如XY轴翻转,笛卡尔坐标和极坐标转换,以满足我们的各种需求。 坐标轴翻转由coord_flip()实现 ggplot(small)+geom_bar(aes(x=cut, fill=cut))+coord_flip() 而转换成极坐标可以由coord_polar()实现: ggplot(small)+geom_bar(aes(x=factor(1), fill=cut))+coord_polar(theta='y') 这也是为什么之前介绍常用图形画法时没有提及饼图的原因,饼图实际上就是柱状图,只不过是使用极坐标而已,柱状图的高度,对应于饼图的弧度,饼图并不推荐,因为人类的眼睛比较弧度的能力比不上比较高度(柱状图) 还可以画靶心图: ggplot(small)+geom_bar(aes(x=factor(1), fill=cut))+coord_polar() 以及风玫瑰图(windrose) ggplot(small)+geom_bar(aes(x=clarity, fill=cut))+coord_polar() 图层(Layer)photoshop流行的原因在于PS 有了图层的概念,使用ggplot画起图来,就更加得心应手。 做为图层的一个很好的例子是蝙蝠侠logo,batman require(ggplot2)f1 <->->function(x) { y1 <->->3*sqrt(1-(x/7)^2) y2 <->->3*sqrt(1-(x/7)^2) y <- c(y1,y2)="" ="" d="">-><- data.frame(x="x,y=y)" ="" d="">-><- d[d$y=""> -3*sqrt(33)/7,] return(d)}x1 <->->3, 7, 0.001), seq(-7, -3, 0.001))d1 <- f1(x1)p1="">-><- ggplot(d1,aes(x,y))="" +="" geom_point(color="">->'red') +xlab('') + ylab('') + theme_bw()x2 <->->4,4, 0.001)y2 <->->2)-(3*sqrt(33)-7)*x2^2/112-3 + sqrt(1-(abs(abs(x2)-2)-1)^2)d2 <- data.frame(x2="x2," y2="y2)p2">-><- p1="" +="" geom_point(data="d2," aes(x="x2,y=y2)," color="">->'yellow')x3 <->->0.75,1,0.001), seq(-1,-0.75,0.001))y3 <->->9-8*abs(x3)d3 <- data.frame(x3="x3," y3="y3)p3">-><- p2+geom_point(data="d3," aes(x="x3,y=y3)," color="">->'green')x4 <->->0.5,0.75,0.001), seq(-0.75,-0.5,0.001))y4 <->->3*abs(x4)+0.75d4 <- data.frame(x4="x4,y4=y4)p4">-><- p3+geom_point(data="d4," aes(x="x4,y=y4)," color="">->'steelblue')x5 <->->0.5,0.5,0.001)y5 <->->2.25,length(x5))d5 <- data.frame(x5="x5,y5=y5)p5">-><- p4+geom_point(data="d5," aes(x="x5,y=y5))x6">-><->->3,-1,0.001), seq(1,3,0.001))y6 <->->6 * sqrt(10)/7 + (1.5 - 0.5 * abs(x6)) * sqrt(abs(abs(x6)-1)/(abs(x6)-1)) - 6 * sqrt(10) * sqrt(4-(abs(x6)-1)^2)/14d6 <- data.frame(x6="x6,y6=y6)p6">-><- p5+geom_point(data="d6,aes(x=x6,y=y6)," colour="">->'blue')multiplot <->->function (..., plotlist = NULL, cols = 1, layout = NULL) { plots <->->...), plotlist) numPlots = length(plots) if (is.null(layout)) { layout <->->1, cols * ceiling(numPlots/cols)), ncol = cols, nrow = ceiling(numPlots/cols)) } if (numPlots == 1) { print(plots[[1]]) } else { grid.newpage() pushViewport(viewport(layout = grid.layout(nrow(layout), ncol(layout)))) for (i in 1:numPlots) { matchidx <- as.data.frame(which(layout="=" i,="" arr.ind="">->TRUE)) print(plots[[i]], vp = viewport(layout.pos.row = matchidx$row, layout.pos.col = matchidx$col)) } }}multiplot(p1,p2,p3,p4,p5,p6, cols=2)-> 分面(Facet)在《ggplot2: 数据分析与图形艺术》一书的翻译中,一开始译者把facet翻译成切片,我在校稿的时候发现了,给他们写信,推荐翻译成分面,如果是slice这个词,翻译成切片倒是很精准,BSD的硬盘分区就叫slice,但facet从词源上看就是小脸的意思,翻译成分面才到位。给他们写信的时候,我还专门查了CNKI翻译助手,发现这词在信息学中,翻成分面早已是固定的。我感觉这是我对这本书翻译的最大贡献,校稿过程中发现的少量小问题远比不上这个关键词意思的把握上。 分面可以让我们按照某种给定的条件,对数据进行分组,然后分别画图。 ggplot(small, aes(x=carat, y=price))+geom_point(aes(colour=cut))+scale_y_log10() +facet_wrap(~cut)+stat_smooth() 主题(Theme)通过ggplot画图之后,我们可能还需要对图进行定制,像title, xlab, p <- ggplot(small)+geom_boxplot(aes(x="cut," y="price,fill=color))p" +="">->'Price vs Cut')+xlab('Cut')+ylab('Price') 但是这个远远满足不了需求,我们需要改变字体,字体大小,坐标轴,背景等各种元素,这需要通过theme()函数来完成。 ggplot2提供一些已经写好的主题,比如 别外ggthemes包提供了一些主题可供使用,包括: theme_economist theme_economist_whitetheme_wsj theme_exceltheme_few theme_foundationtheme_igray theme_solarizedtheme_stata theme_tufte require(ggthemes)p + theme_wsj() 在2013年发表的文章Putative cobalt- and nickel-binding proteins and motifs in Streptococcus pneumoniae中的图3就是使用 至于如何改变这些元素,我觉得我之前画囧字的博文可以做为例子: f <- function(x)="" 1/(x^2-1)x="">-><- seq(-3,3,="" by="0.001)y">-><- f(x)d="">-><- data.frame(x="x,y=y)p">-><- ggplot()p="">-><- p+geom_rect(fill='white' ,color='black' ,size="3,aes(NULL," null,xmin="-3," xmax="3,ymin=-3,ymax=3," alpha="0.1))p">-><- p="" +="" geom_line(data="d," aes(x,y),="" size="3)+ylim(-3,3)theme_null">-><- function()="" {="" ="" theme_bw()="" %+replace%="" ="" theme(axis.text.x="element_blank()," ="" axis.text.y="element_blank()," ="" legend.position='none' ,="" ="" panel.grid.minor="element_blank()," ="" panel.grid.major="element_blank()," ="" panel.background="element_blank()," ="" axis.ticks="element_blank()," ="" panel.border="">-> 详细的说明,可以参考?theme的帮助文档。 二维密度图在这个文档里,为了作图方便,我们使用diamonds数据集的一个子集,如果使用全集,数据量太大,画出来散点就糊了,这种情况可以使用二维密度力来呈现。 ggplot(diamonds, aes(carat, price))+ stat_density2d(aes(fill = ..level..), geom='polygon')+ scale_fill_continuous(high='darkred',low='darkgreen') ggplot2实例蝴蝶图: theta <->->0,24*pi, len=2000)radius <- exp(cos(theta))="" -="">->2*cos(4*theta) + sin(theta/12)^5dd <- data.frame(x="radius*sin(theta)," y="radius*cos(theta))ggplot(dd," aes(x,="">->'')+ylab('') 这个图,我想展示的是对细节的修改上,在画囧字的时候,把画布上的元素都给清除了,我把它定义为theme_null主题,在这里,直接应用,我们可以形成自己的画图风格,并写出自己的主题函数固定下来。 最后以生物界中常用的柱状图+误差图为实例,展示ggplot2非常灵活的图层。以我2011年发表的文章Phosphoproteome profile of human lung cancer cell line A549中的westernblot数据为例。这个实例展示了图层,标尺,主题,注释和各种细节微调多种元素。 Normal <- c(0.83,="" 0.79,="" 0.99,="" 0.69)cancer="">-><- c(0.56,="" 0.56,="" 0.64,="" 0.52)m="">-><- c(mean(normal),="" mean(cancer))s="">-><- c(sd(normal),="" sd(cancer))d="">-><- data.frame(v="c('Normal'," 'cancer'),="" mean="m," sd="s)d$V">-><- factor(d$v,="" levels="c('Normal'," 'cancer'))p="">-><- ggplot(d,="" aes(v,="" mean,="" fill="V," width=".5))p">-><- p+geom_errorbar(aes(ymin="mean," ymax="mean+sd," width=".2)," ="" ="" ="" ="" ="" ="" ="" ="" ="" ="" position="position_dodge(width=.8))p">-><- p="" +="" geom_bar(stat='identity' ,="" position="position_dodge(width=.8)," colour='black' )p="">-><- p="" +="" scale_fill_manual(values="c('grey80'," 'white'))p="">-><- p="" +="" theme_bw()="" +theme(legend.position='none' )="" +="" xlab('')="" +="" ylab('')p="">-><- p="" +="" theme(axis.text.x="element_text(face='bold'," size="12)," ="" ="" ="" ="" ="" ="" ="" axis.text.y="element_text(face='bold'," size="12))p">-><- p+scale_y_continuous(expand="c(0,0)," limits="c(0," 1.2),="" breaks="seq(0," 1.2,="" by=".2))p">-><- p+geom_segment(aes(x="1," y=".98," xend="1," yend="1.1))p">-><- p+geom_segment(aes(x="2," y=".65," xend="2," yend="1.1))p">-><- p+geom_segment(aes(x="1," y="1.1," xend="2," yend="1.1))p">-><- p="" +="" annotate('text',="" x="1.5," y="1.08," label='*'>-> |
|
来自: 昵称39769750 > 《文件夹1》