使用一个工具,要先了解其设计逻辑.
R graphics 像是画家一点一点画图,什么都要要自己设置。matplotlib把图形拆分为一个一个对象,通过设置的对象属性来画图, 这两个绘图逻辑都很容易理解。而ggplot2则更反应数据的本质。
ggplot2的中的gg是 <
数据可视化 就是 从数据到图。我们从解剖数据和图开始
1.数据的维度 variable
ggplot2 绘图的数据须是data.frame 类。以mtcars为例
data.frame 数据是有维度的,每一列代表一个维度,我们这里把每一列称之为一个variable.
2. 图形的组成 轴
以常见的图为例
ggplot(mtcars)+geom_point(aes(x=mpg,y=wt,color=cyl))
ggplot(mtcars)+geom_point(aes(x=mpg,y=wt,color=factor(cyl)))
这幅图对应了三个变量,mpg,wt,cyl,分别对应X轴,Y轴,和颜色bar,他们都对应一个连续变量。从 "内涵"上说,他们都对应一个data.frame的一列,即“一个variable”.
从 "外形"上说,都有断点,断点都有label, 都有子的名字。
因此 颜色bar和X轴,Y轴是一样的,我们都把他们称为图形的"轴"。这里的轴就是ggplot2的aesthetics组件, 之所以此处称之为“轴”,是因为对初学者来说,aesthetics直译是“美学”,有些让人不知所云。
这副point图包括了三个轴,X轴,Y轴,颜色轴,每个轴都有自己的name,分别为mpg,wt,cyl,轴上都有breaks和对应的label, name,breaks,label 是轴的三个基本属性。
轴是图形的有效部分,承载了原data.frame的信息,是图形的“信息部分”。其他如背景线,标签位置,颜色调整等只是图形的修饰,并不承担信息。ggplot2的优点之一就是 只需要关注图形的信息部分,其他修饰有默认设置。
3.映射mapping(数据有维,图形有轴)
上图,每个轴实际上表示了一个dataframe的variable。mtcars的mpg信息完全反映在X轴,wt信息完全反映在y轴,cyl信息完全反映在颜色轴。
因此,数据有维,图形有轴,ggplot2的基本绘图思想,就是把data.frame的variable投射到图形的轴上。这个过程叫映射mapping。
继续以上图为例,我们来看颜色轴,cyl的信息完映射aes到了图形的颜色轴。
ggplot2对图形的轴有内置的默认设置,以color轴为例,对于point图,color轴默认有2个,一个连续的色带,一个是离散的点. aes(color=cyl)做的事情就是把 cyl信息 转变为color信息。
可以想象,在data.frame中cyl是连续变量,所以aes会把cyl信息映射到连续的色带,就是默认的蓝色色带。
这个过程很容易理解。对应好后,给色带指定break和label.
如果数据改变了,连续变量cyl多了一个9,那么9会对应到色带的最高点,4对应的颜色还是不变.
如果cyl是离散变量,那么就会按factor顺序对应到内置的离散颜色轴,这个轴只有8个颜色,随意如果变量factor有9个level,那么第9个level会和第1个level映射后的颜色相同。
4.geom 几何图形
geom是图形函数,指定了图形类型。如上geom_point 是声明画一个点图,那么就应该知道每个点的属性。geom_point的参数包括 x,y,color,shape,size,alpha等,这正是画点图所需要的每个点的属性,有了这些信息,geom_point就可以画出图形了。显然,在这几个参数中,x,y是必须的。
ggplot2在绘图前主要工作就是把variable转换成这些图形需要的轴。
p <- ggplot(mtcars)+geom_point(aes(x=mpg,y=wt,color=cyl))
p$data ## 即原始绘图数据data.frame
dim(p$data) ## 32行
g <- ggplot_build(p) ## 查看stat后的信息。g$plot即为图形
stated <- g$data[[1]] ## geom的绘图信息
dim(stated ) ## 32行
数据是这样的,原来的data.frame 数据aes后实际上变成了点图(geom_point)所需的信息,
如上图, 这个数据实际上完全等价于图形,geom_point就是根据这个表达渲染出图形的。
5.geom的轴:aesthetic组件
所谓 aesthetics组件, 就是图形的“轴”, ggplot2中常用的有
颜色类:color(颜色或边框颜色)、fill(填充颜色)和alpha(透明度)
形状类:linetype(线型)、size(点的大小或线的宽度)和shape(形状)
位置类:x、y、xmin、xmax、ymin、ymax、xend、yend
分组:group
不同的geom有不同的轴。ggplot2是2d平面绘图,所以x,y是几乎对所有geom必须的.
6.stat+geom
每个geom同时也是一个stat(统计变换),这句话怎么理解呢?
以上画的点图,这个太容易理解,很直观,几乎不需要stat.我们看个略复杂点的。
继续以mtcats为例。geom_bar
dat<-mtcars
dat$cyl <- paste0("cyl",dat$cyl)
ggplot(dat)+geom_bar(aes(x =cyl))
然后就出了这个很粗糙的图,虽然粗糙,但是已经包含了所有需要的信息。geom_bar,我们先看下 ?geom_bar所需要的轴,在geom_bar的帮助文档中Aesthetics部分有x,y,alpha,color,fill,froup,linetype,size。实际上,我们要画个bar图,那么我们需要的信息是:多少个bar,每个bar的X轴位置,高度(Y轴位置),alpha,color,fill,froup,linetype,size信息。其中x,y是必须的,其他可以用默认值。
似乎有点不对,只是一个离散变量cyl映射到了x轴啊,y轴信息从哪来的,别急,这幅图的真实映射是这样的。
X轴对啥,是分类变量cyl的levle. 真实的x轴对应如分类 x= c("cyl4","cyl5","cyl6")
y轴是x轴每个level的count. 真实的Y轴对应连续变量 y=c(11,7,14)
其他aesthetics参数使用默认值,然后geom_bar就可以渲染出上图。
在这个从 x= cy l到 x=cyl的level, y=cyl的count, 中间需要有一个统计变换的,这部分工作是由stat完成的,也就是geom_bar的stat参数,geom_bar默认的是stat="count".
画不同的geom需要不同stat,对于多数geom来说,geom外观就已经决定了应该如何stat,所以多数geom只能对应一个stat.
ggplot2还把stat单独作为函数,也就是一系列stat函数,同样,stat后的信息就是画图所需要的data.frame信息,加上geom参数信息,就包括了渲染图形所需要的信息,就可以画图图形了。这是stat为什么也能画图的原因。上图图形的stat信息,3个bar的信息如下图。
7.aesthetic写在aes内与写在aes外
geom的aesthetic,如color,写在aes内和外
ggplot(mtcars)+geom_point(aes(x=mpg,y=wt,color=cyl)) ## 需要的图
ggplot(mtcars)+geom_point(aes(x=mpg,y=wt,color="blue") ##所有点红色
ggplot(mtcars)+geom_point(aes(x=mpg,y=wt),color="blue") ##所有点蓝色
我们来
上述第一句哈,是mtcars的cyl 映射到 color轴,可以得到正确的颜色。
第二句实际上是geom_point(mapping=aes(x=mpg,y=wt,color="blue"))。 'blue' 映射到color轴,'blue'实际上是从c('blue'),是个长度为1的字符串,离散型变量,所以映射函数会把从c('blue')映射到 离散型的默认color轴,第一个颜色是红色,所以所有点是红色。注意映射函数接受长度为1或者长度和x,y等长的vector.
第三句话,geom_point(mapping=aes(x=mpg,y=wt),color="blue")写在aes外,不需要经映射函数处理,在geom内,相当于给geom直接指定了'blue'颜色(上述stated数据的color列),'blue'是R内置的颜色。如果在上述geom_bar中,color可以接受长度为1或者3的vector.
所以可以在原data.frame加上一列color等,填充自己需要的颜色,然后不aes,就是对应的颜色。
结合6和7部分,你也可以自己stat原data.frame到 geom 需要的变量, 然后直接把这些变量不aes,赋予geom的轴,直接出图。
8.scale系列函数
还是以颜色轴为例,变量cyl映射为 一条 蓝色色带(geom_point默认),但是我不喜欢这条蓝色色带,我想使用别的颜色怎么办?这就需要scale.scale本身由“按比例”的意思。
scale是更改默认的轴,并重新建立映射关系。每个轴都有两种形式,离散的和连续的。
所以scale系类函数基本形式都是这样的
scale_aesthetics(轴)_discrete or continuous.
而形如scale_color_brewer只是scale_color_discrete的其中一种快捷函数。
所有的轴都有三个共同的参数,name,breaks,label.
修改轴的name是很常见的操作,所有有几个快捷函数。
labs(aesthetics=" newname")可以修改某个轴的名字
xlab("newname"),修改X轴名字,实际上是scale_x_discrete or continuous(name=""newname"")
同理,ggplot2中scale相关快捷函数有很多。
以下三种写法是一样的
ggplot(mtcars)+geom_point(aes(x=mpg,y=wt,color=cyl))+scale_color_continuous(name="newname")
ggplot(mtcars)+geom_point(aes(x=mpg,y=wt,color=cyl))+xlab("newname")
ggplot(mtcars)+geom_point(aes(x=mpg,y=wt,color=cyl))+labs(x='newname')
9 图层叠加
ggplot2的另一个强大之处是图层叠加。此处指信息载体的”geom_xxxx" 的叠加。但是这个时候应该注意的是ggplot2是2D绘图,不同的"geom_xxxx"至少要使用共同的x轴,y轴,有时还有使用共同的颜色轴等。这个时候要注意,后面的“geom__xxxx”的x,y轴会覆盖前面的“geom_xxxx”的x,y轴。这个在作图前要规划好。
综上ggplot2的强大之处在于其逻辑性,绘图时使我们能“关注数据”,而非图形细节。相比之选使用graphics,不得不把更多精力放在图形上,而非数据上。