2020-03-30 复习ggplot2

学习资料:https://mp.weixin.qq.com/s/r6pfSU-88e86cUjxp3yFnQ 网红教授Y书原创公众号教程ggplot2专题

一、理解数据和映射

下面以内置数据集钻石的数据为例,这份数据总共有53940行10列,随机取一个子集来画图。

rm(list = ls())
library(ggplot2)
data(diamonds)
dim(diamonds)
set.seed(100)
dat <- diamonds[sample(nrow(diamonds), 1000), ]
head(dat)

查看随机取的子集前几行

> dim(diamonds)
[1] 53940    10
> head(dat)
# A tibble: 6 x 10
  carat cut     color clarity depth table price     x     y     z
               
1  1.26 Ideal   G     SI1      59.6    57  6738  7.08  7.04  4.21
2  0.7  Ideal   D     VS2      62.7    57  3448  5.65  5.67  3.55
3  0.36 Ideal   F     SI1      62      56   770  4.59  4.54  2.83
4  2.1  Premium J     SI2      59.1    58 12494  8.46  8.4   4.98
5  1.21 Premium D     SI2      59.7    58  4946  7.06  6.96  4.19
6  2    Good    E     SI2      64.7    57 15393  7.75  7.86  5.05

以克拉数为X轴变量,价格为Y轴变量。

p <- ggplot(data = dat, mapping = aes(x = carat, y = price))
p + geom_point()
图1,理解映射

如果想将切工(cut)映射到形状属性。在aes中添加参数:

p <- ggplot(data=dat, mapping=aes(x=carat, y=price, shape=cut))
p+geom_point()
图2,在映射里面加一个参数改变了显示的形状

再加一个参数添加颜色:

p <- ggplot(data=dat, mapping=aes(x=carat, y=price, shape=cut, colour=color))
p+geom_point()
图3,添加颜色映射

二、理解几何对象(Geometric)

在上面的例子中,各种属性映射由ggplot函数执行,只需要加一个图层,使用geom_point()告诉ggplot要画散点,于是所有的属性都映射到散点上。

geom_point()完成的就是几何对象的映射,ggplot2提供了各种几何对象映射,如geom_histogram用于直方图,geom_bar用于画柱状图,geom_boxplot用于画箱线图等等。ggplot2提供了很多的geom_xxx函数来完成相应的几何映射,可以满足我们对各种图形绘制的需求。

geom_abline     geom_area   
geom_bar        geom_bin2d
geom_blank      geom_boxplot    
geom_contour    geom_crossbar
geom_density    geom_density2d  
geom_dotplot    geom_errorbar
geom_errorbarh  geom_freqpoly   
geom_hex        geom_histogram
geom_hline      geom_jitter     
geom_line       geom_linerange
geom_map        geom_path   
geom_point      geom_pointrange
geom_polygon    geom_quantile   
geom_raster     geom_rect
geom_ribbon     geom_rug    
geom_segment    geom_smooth
geom_step       geom_text   
geom_tile       geom_violin
geom_vline

不同的几何对象,要求的属性会有些不同,这些属性也可以在几何对象映射时提供,比如上一图,也可以用以下语法来画:

p <- ggplot(dat)
p+geom_point(aes(x=carat, y=price, shape=cut, colour=color))

下面就是几个常见的几何映射示例:

直方图

直方图最容易,提供一个x变量,画出数据的分布。

ggplot(dat)+geom_histogram(aes(x=price, fill=cut))
图4

展示效果不太好,也可以将其分开,side-by-side地画直方图。

ggplot(dat)+geom_histogram(aes(x=price, fill=cut), position="dodge")
图5在图4的基础上改进了

还可以使用position=”fill”,按照相对比例来画。就是常见的堆积柱状图

ggplot(dat)+geom_histogram(aes(x=price, fill=cut), position="fill")
图6,堆积柱状图

柱状图非常适合于画分类变量。

柱状图是用来表示计数数据的,但在生物界却被经常拿来表示均值,加上误差来表示数据分布,这可以通常图层来实现,我将在图层一节中给出实例。

密度函数图

密度函数图,数据和映射和直方图是一样的,唯一不同的是几何对象函数,geom_histogram告诉ggplot要画直方图,而geom_density则是画密度函数图,直接套用即可:

ggplot(dat)+geom_density(aes(x=price, colour=cut))
密度直方图

改变一个参数

ggplot(dat)+geom_density(aes(x=price,fill=clarity))

结果如下:


密度直方图

colour参数指定的是曲线的颜色,而fill是往曲线下面填充颜色。

箱式图

数据量比较大的时候,用直方图和密度函数图是表示数据分布的好方法,而在数据量较少的时候,比如很多的生物实验,很多时候大家都是使用柱状图+errorbar的形式来表示,不过这种方法的信息量非常低,被Nature Methods吐槽,这种情况推荐使用boxplot(箱式图或箱线图)。

ggplot(dat)+geom_boxplot(aes(x=cut, y=price,fill=color))
图9.箱线图

更换几何对象映射函数geom_boxplot将数据映射到箱式图上,按切工(cut)分类,对价格(price)变量画箱式图,再分开按照color变量填充颜色。

三、修改标尺

分类属性映射标尺修改

在对图形属性进行映射之后,使用标尺可以控制这些属性的显示方式,比如坐标刻度,可能通过标尺,将坐标进行对数变换;比如颜色属性,也可以通过标尺,进行改变。

ggplot(dat)+geom_point(aes(x=carat, y=price, shape=cut, colour=color))+
  scale_y_log10()+
  scale_colour_manual(values=rainbow(7))

结果如下:


图10

以第一部分数据和映射示例中所画散点图为例,将Y轴坐标进行log10变换,再自己定义颜色为彩虹色。

统计变换(Statistics)标尺修改

统计变换对原始数据进行某种计算,然后在图上表示出来,例如对散点图上加一条回归线。

ggplot(dat, aes(x=carat, y=price))+
  geom_point()+
  scale_y_log10()+
  stat_smooth()
图11

注意:

  • 这里就不按颜色、切工来分了,不然ggplot会按不同的分类变量分别做回归,图就很乱,如果我们需要这样做,我们可以使用分面
  • 这里,aes所提供的参数,就通过ggplot提供,而不是提供给geom_point,因为ggplot里的参数,相当于全局变量,geom_point()和stat_smooth()都知道x,y的映射,如果只提供给geom_point(),则相当于是局部变量,geom_point知道这种映射,而stat_smooth不知道,当然你再给stat_smooth也提供x,y的映射,不过共用的映射,还是提供给ggplot更好。

ggplot2提供了多种统计变换方式:

stat_abline       stat_contour      stat_identity     stat_summary
stat_bin          stat_density      stat_qq           stat_summary2d
stat_bin2d        stat_density2d    stat_quantile     stat_summary_hex
stat_bindot       stat_ecdf         stat_smooth       stat_unique
stat_binhex       stat_function     stat_spoke        stat_vline
stat_boxplot      stat_hline        stat_sum          stat_ydensity

统计变换是非常重要的功能,我们可以自己写函数,基于原始数据做某种计算,并在图上表现出来,也可以通过它改变geom_xxx函数画图的默认统计参数。

四、坐标系统(Coordinante)

坐标系统控制坐标轴,可以进行变换,例如XY轴翻转,笛卡尔坐标和极坐标转换,以满足我们的各种需求。

坐标轴翻转由coord_flip()函数实现

ggplot(dat)+geom_bar(aes(x=cut, fill=cut))+coord_flip()

图12

而转换成极坐标可以由coord_polar()函数映射实现:

ggplot(dat)+geom_bar(aes(x=factor(1), fill=cut))+coord_polar(theta="y")
图14

这也是为什么之前介绍常用图形画法时没有提及饼图的原因,饼图实际上就是柱状图,只不过是使用极坐标而已,柱状图的高度,对应于饼图的弧度,饼图并不推荐,因为人类的眼睛比较弧度的能力比不上比较高度(柱状图)。
还可以画靶心图:

ggplot(dat)+geom_bar(aes(x=factor(1), fill=cut))+coord_polar()
图14靶心图

风玫瑰图(windrose)

ggplot(dat)+geom_bar(aes(x=clarity, fill=cut))+coord_polar()
图15

五、图层

图层概念在上面的散点图加回归曲线已经展示过了,还可以展示更复杂的,这就是ggplot2的优秀之处了,Y叔举了个蝙蝠图的例子我就不重复了。

六、分面(Facet)

在《ggplot2: 数据分析与图形艺术》一书的翻译中,一开始译者把facet翻译成切片,Y叔推荐翻译成分面,分面可以让我们按照某种给定的条件,对数据进行分组,然后分别画图。
在统计变换一节中,提到如果按切工分组作回归线,显然图会很乱,有了分面功能,我们可以分别作图。

ggplot(dat, aes(x=carat, y=price))+
  geom_point(aes(colour=cut))+
  scale_y_log10() +
  facet_wrap(~cut)+
  stat_smooth()
图16,分面图

七、主题(Theme)

通过ggplot画图之后,我们可能还需要对图进行定制,像title, xlab,
ylab这些高频需要用到的,自不用说,ggplot2提供了ggtitle(),
xlab()和ylab()来实现。 比如:

p <- ggplot(dat)+geom_boxplot(aes(x=cut, y=price,fill=color))
p + ggtitle("Price vs Cut")+xlab("Cut")+ylab("Price")

图17

但是这个远远满足不了需求,我们需要改变字体,字体大小,坐标轴,背景等各种元素,这需要通过theme()函数来完成。

ggplot2提供一些已经写好的主题,比如theme_grey()为默认主题,我经常用的theme_bw()为白色背景的主题,还有theme_classic()主题,和R的基础画图函数较像。

别外ggthemes包提供了一些主题可供使用,包括:

theme_economist theme_economist_white
theme_wsj       theme_excel
theme_few       theme_foundation
theme_igray     theme_solarized
theme_stata     theme_tufte
library(ggthemes)
p + theme_wsj()
图18

二维密度图

在这个文档里,为了作图方便,我们使用diamonds数据集的一个子集,如果使用全集,数据量太大,画出来散点就糊了,这种情况可以使用二维密度力来呈现。

ggplot(dat, aes(carat, price))+ 
  stat_density2d(aes(fill = ..level..), geom="polygon")+ 
  scale_fill_continuous(high='darkred',low='darkgreen')
图19

数据太多就容易糊。

ggplot2实例

Y叔列了蝴蝶图,囧字图等好玩搞怪的图,最后以生物界中常用的柱状图+误差图为实例,展示了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="*")
print(p)
图20

在这个专题中还有2个神器:

  • 《不需要花时间去学ggplot2主题系统》 中讲到的一个RStudio插件,只需要使用以下指令安装R包:
install.packages("ggThemeAssist")

然后愉快的用鼠标点点点就能完成细节了。

  • 代码无感者的福音,小白也能ggplot2画出高大上的图

ggplot2不单单能出更多更好看的图,而且出图并不比GraphPad Prism困难,除了有调整细节的插件,还有点点鼠标就可以画图的插件- esquisse

你可以使用下面的指令安装:

devtools::install_github("dreamRs/esquisse")

然后就可以在RStudio中通过点鼠标,愉快地用ggplot2画图了

esquisse::esquisser()

具体使用方法可以点上面的链接看Y叔编辑的动图,也可以参考作者的教程:https://www.jianshu.com/p/ecfa0d640250
探索数据的时候可以用,而且还可以导出画图代码,简直不要太优秀!
这感觉就跟抄作业一样。

你可能感兴趣的:(2020-03-30 复习ggplot2)