R语言作图点滴积累,今天要记录ggplot2中散点图的做法。散点图算是数据展示中非常基础的一种方法了吧,一般用于展示两个变量之间的关系(比如线性相关)。按照惯例,我每次讲一个新的图都会用一个我实际使用的例子,先来说说今天做这个散点图的例子吧:
问题描述:
我有两个变量,一个变量是蛋白相互作用网络中节点的度(degree),另一个变量是这些蛋白参与形成的复合物的个数;现在我想看看,一个蛋白参与形成的复合物个数(Number of complexes)是否跟它的度(degree)相关。
上面描述的这个问题,就是一个很典型的可以通过散点图来展示的例子。先来个数据快照(显示前10个数据点):
ProteinID | No. complex | Degree |
---|---|---|
P1 | 188 | 125 |
P2 | 128 | 76 |
P3 | 119 | 102 |
p4 | 95 | 66 |
P5 | 95 | 110 |
P6 | 80 | 68 |
P7 | 66 | 61 |
P8 | 57 | 84 |
P9 | 46 | 40 |
P10 | 46 | 45 |
漂亮的散点图要一步一步来
1. 首先来个简单的散点图
#Import data
> dat <- read.table("ProteinDegree_complex.txt",header = TRUE)
#plot a simple scatter plot
> library(ggplot2)
> p <- ggplot(dat,aes(x=degree,y=complex)) + geom_point(shape=19)) +
xlab("Degree") + ylab("Number of complexes")
> p
note:
- geom_point(): 是画散点图的函数,里面可以添加各种参数,用于设置散点图的形状、大小、颜色等,比如形状shape = 19, 表示的是较大的实心原点
-
xlab和ylab:两个函数分别设置x和y坐标轴的标题
这个简单的散点图看起来是这样滴:
2. 如果想要拟合一条直线呢
#Import data
> dat <- read.table("ProteinDegree_complex.txt",header = TRUE)
#plot a simple scatter plot
> library(ggplot2)
> p <- ggplot(dat,aes(x=degree,y=complex)) + geom_point(shape=19)) +
xlab("Degree") + ylab("Number of complexes") +
geom_smooth(method = lm)
> p
ggplot2 提供一个函数自动添加拟合的曲线(包括直线),当然该函数底层肯定是做了拟合分析的,比如线性回归分析等。
- geom_smooth():这个函数就是为散点图添加一条平滑的曲线(包含直线),它有个参数method, 指定曲线平滑方法,可选"lm", "glm", "gam", "loess", "rlm",这几个具体表示什么意思,大家动动手,自己谷歌之,默认会使用"loess"。
下面两个图分别是使用了"lm"和"loess":
给散点图加了直线,可是这个直线拟合得怎么样,以及拟合的直线的参数ggplot2并没有提供,为了图的信息更完整,我们应当考虑给这个拟合的直线加上公式,以及拟合的R2值。这样之后,我们从图上可以得到些什么信息呢?
首先,我们可以很容易知道degree和complex数目是呈正相关关系的,通过拟合直线和公式可以知道两个变量的线性关系强弱;然后,然后就是一堆不知道是啥的黑点...
总感觉还是缺少些什么,仔细看看这个散点图,你会不会想知道图中degree很高且参与很多复合物的这几个蛋白是什么?这样的蛋白一定是生物细胞中十分重要的蛋白。所以呢,我们可以把最靠近右上角的前10个点给高亮出来,甚至给这些点表示label(基因名)。说干就干,看代码:
#Import data
> dat <- read.table("WD40_complex_degree.out",header = TRUE)
#edit the formula for the fitted line
> formula <- sprintf("italic(y) == %.2f %+.2f * italic(x)",
round(coef(dat.lm)[1],2),round(coef(dat.lm)[2],2))
r2 <- sprintf("italic(R^2) == %.2f",summary(dat.lm)$r.squared)
labels <- data.frame(formula=formula,r2=r2,stringsAsFactors = FALSE)
#plot the simple scatterplot
> p <- ggplot(dat,aes(x=degree,y=complex,colour=degree>=63)) + geom_point(shape=19) +
xlab("Degree of WD40 proteins") + ylab("Number of complexes")
#linear regression analysis
> dat.lm <- lm(complex ~ degree, data = dat)
#add a line and labels for the formula
> p <- p + geom_abline(intercept = coef(dat.lm)[1],slope = coef(dat.lm)[2]) +
geom_text(data=labels,mapping=aes(x = 15,y=175,label=formula),parse = TRUE,inherit.aes = FALSE,
size = 6) +
geom_text(data=labels,mapping=aes(x = 15,y=165,label=r2),parse = TRUE,inherit.aes = FALSE,
size = 6) +
#add labels(gene name) for top 10 degree-ranked proteins
annotate(geom = "text",x=annoText$degree-1,y=annoText$complex-2,label=annoText$WD40id, size=4.0)
> p + theme(legend.position = "none") + theme(axis.title = element_text(size = 16),
axis.text = element_text(size = 12,colour="black"))
代码一下子长了好多(囧),我们可以与前面的比较下,
- 首先画简单散点图的那部分代码(间代码注释)添加了"colour = degree>=63",这句的目的其实是对所有点根据条件“degree>=63”进行了分组,不同颜色表示;
- 其次,发现这里少了一句代码,对了,就是geom_smooth(method=lm),因为前面加了分组信息,geom_smooth会在不同组里分别拟合曲线,这并不是我们想要的,我们只是想高亮出一些点而已。所以,这里先不直接拟合了, 后面再手动拟合并添加直线;
- lm(complex ~ degree, data = dat):这个是手动做线性回归分析
- geom_abline():根据上面回归分析,画拟合的直线,从上面的分析中提取出 截距 coef(dat.lm)[1]和 斜率 coef(dat.lm)[2])即可;
- geom_text():这个函数给图中添加了拟合直线的公式和R2;这里我们提供了新的data,所以,要注意的是后面inherit.aes = FALSE这个设置很重要,表示我们不继承ggplot函数中使用的data,不然会报错。
- annotate():这个函数通过制定geom="text",在图中指定的地方画上标签,可以提供坐标
- theme(legend.position = "none"):去除legend,这里我做的时候也出现一个问题,去除legend的另一种方法是p + guides(fill = FALSE),但是,我最新使用这个代码的时候,并没有起作用,不知道是不是我的Rstudio没有反应还是出现bug了,大家可以自己试试;
- theme(axis.title...):这些都是对图中的文字进行美化一下,加大坐标轴标题的文字啊之类的。
最后的图是这个样子的: