R语言近期记录(201911)
本文是笔者近期使用R语言的一个简单记录。
本文包括以下五个小节:
- ggplot2 手动调整线条颜色
- ggplot2 修改坐标轴
- ggplot2 组合图形
- ggplot2 多图
- dplyr包中 filter 函数的一个坑
ggplot2 手动调整线条颜色
主要是用到scale_color_manual
函数,举例来说:
下面代码是生成一幅折线图,但是线条颜色是软件自动设置的。
n <- 5
x0 <- 1:n
y1 <- x0 + 10
y2 <- x0 + 20
y3 <- x0 + 30
d <- data.frame(x=paste0("X", rep(x0, times=3)), y=c(y1, y2, y3), g=rep(c("a", "b", "c"), each=n))
d$x <- factor(d$x, levels=paste0("X", 1:n))
library(ggplot2)
ggplot(d, aes(x=x, y=y, group=g, color=g)) + geom_point() + geom_line()
生成的图片如下:
可以看出,一共三组数据,每组数据的线条颜色是软件自动设置的。如果添加scale_color_manual语句可以手动设置线条的颜色:
ggplot(d, aes(x=x, y=y, group=g, color=g)) + geom_point() + geom_line() +scale_color_manual(values=c("a"="red", "b"="blue", "c"="black"))
修改后的图片如下:
类似的函数还有scale_fill_manual
,scale_size_manual
,scale_shape_manual
,scale_linetype_manual
,scale_alpha_manual
,scale_discrete_manual
等。以scale_fill_manual函数为例,从其名字上就可以看出,该函数可以手动设置填充色。
ggplot2 修改坐标轴
修改坐标轴主要用到scale_x_continuous
,scale_y_continuous
,scale_x_discrete
,scale_y_discrete
这四个函数。从这些函数的名称上可以看出,分别是针对x轴和y轴的,continuous和discrete分别是针对连续型数据和离散型数据来说的。
这些函数可以对坐标轴的诸多细节进行调整,以笔者遇到的问题为例:如果x轴要画100个点,如果这些点的标签都显示出来,会挤在一起不美观。像下面这样:
其代码如下:
n <- 100
x0 <- 1:n
y1 <- x0 + 10
y2 <- x0 + 20
y3 <- x0 + 30
d <- data.frame(x=paste0("X", rep(x0, times=3)), y=c(y1, y2, y3), g=rep(c("a", "b", "c"), each=n))
d$x <- factor(d$x, levels=paste0("X", 1:n))
library(ggplot2)
ggplot(d, aes(x=x, y=y, group=g, color=g)) + geom_point() + geom_line() +scale_color_manual(values=c("a"="red", "b"="blue", "c"="black"))
即使旋转坐标轴标签也没有多少改观:
ggplot(d, aes(x=x, y=y, group=g, color=g)) + geom_point() + geom_line() +scale_color_manual(values=c("a"="red", "b"="blue", "c"="black")) +theme(axis.text.x=element_text(angle=45, hjust=.9)) # 旋转坐标轴标签
这个时候可以使用scale_x_discrete语句,只显示其中部分标签:
ggplot(d, aes(x=x, y=y, group=g, color=g)) + geom_point() + geom_line() +scale_color_manual(values=c("a"="red", "b"="blue", "c"="black")) +scale_x_discrete(breaks=paste0("X", seq(10, 100, 10))) # 只显示部分标签
效果如下:
上面的代码用到了scale_x_discrete函数的breaks
参数,该参数控制着显示哪些标签。scale_x_discrete函数还有其它参数控制着坐标轴的诸多细节,比如limits
参数,该参数可以控制坐标轴标签显示的顺序。比如我们接着上面的代码,将x轴的显示顺序从X1到X100调整为从X100到X1。
ggplot(d, aes(x=x, y=y, group=g, color=g)) + geom_point() + geom_line() +scale_color_manual(values=c("a"="red", "b"="blue", "c"="black")) +scale_x_discrete(breaks=paste0("X", seq(10, 100, 10)), # 只显示部分标签limits=paste0("X", n:1)) # 调整x轴标签顺序
其它的参数也是很有用的,有机会大家可以研究。
ggplot2 组合图形
组合图形就是在一张图上叠加多个图形,这多个图形分别在不同的图层上。实际上ggplot2中的组合图形一般就是叠加图层。比如,最常见的折线图其实就是一个组合图形,它包含了点图和线图这两个图层的叠加。还以上面的数据为例:
n <- 100
x0 <- 1:n
y1 <- x0 + 10
y2 <- x0 + 20
y3 <- x0 + 30
d <- data.frame(x=paste0("X", rep(x0, times=3)), y=c(y1, y2, y3), g=rep(c("a", "b", "c"), each=n))
d$x <- factor(d$x, levels=paste0("X", 1:n))
library(ggplot2)
ggplot(d, aes(x=x, y=y, group=g, color=g)) + geom_point() + # 先是点图geom_line() # 后是线图
图层的顺序是很重要的,因为后面的图层会“盖”住前面的图层,有可能会影响前面图层的显示效果。比如,还是上面的数据,下面的代码先画箱线图,再画线图,正常显示:
ggplot(d, aes(x=g, y=y)) + geom_boxplot() + # 箱线图stat_summary(fun.y="mean", color="red", geom="line", group=1) # 各组平均值的连线
从图中可以看出,上图一共三组数据,每组数据的箱线图和平均值的连线都可以正常显示。但是,如果颠倒图层的顺序,先画线图,再画箱线图,那么箱线图会盖住线图,从而影响整体的显示效果:
ggplot(d, aes(x=g, y=y)) + stat_summary(fun.y="mean", color="red", geom="line", group=1) + # 各组平均值的连线geom_boxplot() # 箱线图
我们从上图可以看到,图层的顺序是很重要的。
其实,上面的代码中用stat_summary
函数实现了平均值的线图,其实我们可以用一般的geom_line
来实现,只不过需要对数据进行一下处理。因为我们是要求各组的平均值,所以先用一个数据框来存储各组平均值。
d_aver <- aggregate(d$y, list(g=d$g), mean) # 各组平均值
然后,我们对两个不同的数据框分别作箱线图和线图:
d_aver <- aggregate(d$y, list(g=d$g), mean) # 各组平均值
ggplot() + geom_boxplot(data=d, aes(x=g, y=y)) + # 箱线图geom_line(data=d_aver, aes(x=g, y=x, group=1, color="red")) # 各组平均值的连线
其实正如stat_summary
函数的名称显示的那样,这是一个统计画图函数,我们当然可以自己先统计然后画图。比如上面的例子,用处理过的数据经geom_line
函数画出来的图和stat_summary画出来的图是一样的。
还有一点值得注意,就是上面的代码中,geom_boxplot函数和geom_line函数分别用了不同的数据集,这一点很有意思,也就意味着不同的图层可以用不同的数据来作图。实际上,不光是数据可以不同,不同的图层还可以使用不同的映射(mapping)。ggplot2的设计思路有点像面向对象编程里面的类的继承
,ggplot
函数是“基类”,它的参数值会被下面的各个图层所继承,而各个图层是相互独立的,它们可以修改自己图层中的参数值(或者说是覆盖掉ggplot函数的参数值),而不会影响其它图层以及ggplot函数的参数值。这一点可以用下面的代码来验证以下:
d_aver <- aggregate(d$y, list(g=d$g), mean) # 各组平均值
p <- ggplot() + geom_boxplot(data=d, aes(x=g, y=y)) + # 箱线图geom_line(data=d_aver, aes(x=g, y=x, group=1), color="red") # 各组平均值的连线
p$layers # 显示各个图层的参数
ggplot2 多图
我们经常要将多幅图放在一起,ggplot2 处理这个问题常用两种方式,一是用ggplot2本身的facet
,二是利用与ggplot2相关的一个包gridExtra
。
首先看分面的方式(facet),有facet_wrap
函数和facet_grid
函数。我们看一个例子:
n <- 5
x0 <- 1:n
y1 <- x0 + 10
y2 <- x0 + 20
y3 <- x0 + 30
d <- data.frame(x=paste0("X", rep(x0, times=3)), y=c(y1, y2, y3), g=rep(c("a", "b", "c"), each=n))
d$x <- factor(d$x, levels=paste0("X", 1:n))
library(ggplot2)
# 采用分面(facet)
# 这里用facet_wrap函数比较合适:
ggplot(d, aes(x=x, y=y)) + geom_line(group=1) + facet_wrap(~g, nrow=2)
画出来的效果是:
上面的例子比较适合facet_wrap函数,当然,使用facet_grid函数也是可以的:
# 当然,用facet_grid函数也可以:
ggplot(d, aes(x=x, y=y)) + geom_line(group=1) + facet_grid(.~g)
画出来的效果是:
说完了facet,我们再看看gridExtra包。这个R包可以将多个图片组合成一张大图。笔者常用包中的marrangeGrob
函数。将要组合的多个图放入一个list中即可,还以上面的数据为例:
n <- 5
x0 <- 1:n
y1 <- x0 + 10
y2 <- x0 + 20
y3 <- x0 + 30
d <- data.frame(x=paste0("X", rep(x0, times=3)), y=c(y1, y2, y3), g=rep(c("a", "b", "c"), each=n))
d$x <- factor(d$x, levels=paste0("X", 1:n))
library(ggplot2)
library(gridExtra)
oneGrob <- function(g) { # 生成单张小图data <- d[d$g == g, ]ggplot(data, aes(x=x, y=y)) + geom_line(group=1) + labs(title=paste0("group=", g)) +theme(plot.title = element_text(hjust=0.5))
}
lgrob <- lapply(unique(d$g), oneGrob) # 将多张小图放到一个list中
# 将多张小图组合成一张大图
marrangeGrob(lgrob, nrow=2, ncol=2, top="Example of marrangeGrob function")
其效果是:
我们可以看到,图片是按照列优先的顺序进行排列的,如果要按照行的顺序进行排列,可以调整marrangeGrob函数的layout_matrix
参数,像下面这样:
marrangeGrob(lgrob, nrow=2, ncol=2, layout_matrix = matrix(1:4, 2, 2, byrow=T), # 设置byrow=T,按行排列小图top="Example of marrangeGrob function")
dplyr包中 filter 函数的一个坑
自从笔者接触dplyr
包以来,使用它的频率越来越高。但是,笔者近期在使用该包的filter
函数时,遇到一个问题。以上面的数据为例,假设要挑选出"a"组的数据,将其它组的数据过滤掉,可以这样:
n <- 5
x0 <- 1:n
y1 <- x0 + 10
y2 <- x0 + 20
y3 <- x0 + 30
d <- data.frame(x=paste0("X", rep(x0, times=3)), y=c(y1, y2, y3), g=rep(c("a", "b", "c"), each=n))
d$x <- factor(d$x, levels=paste0("X", 1:n))
library(dplyr)
# 过滤前各组数据量统计
table(d$g)
# 过滤
g <- "a" # 过滤后剩下的组的组名
d1 <- d %>% filter(g == g)
table(d1$g) # 过滤失败
过滤失败的原因是filter函数中的过滤条件没有发挥作用,因为g == g
在filter函数中恒成立,其实是犯了变量重名的一个错误,把代码改动一下即可:
# 重新过滤
g <- "a" # 过滤后剩下的组的组名
g2 <- g # 为了避免变量重名,另赋值一个变量
d2 <- d %>% filter(g == g2)
table(d2$g) # 过滤成功
(公众号:生信了)
R语言近期记录(201911)相关推荐
- R语言小白记录1:如何数一个data的行列数
小白开始记录自己的R语言学习过程. 遇到的问题:如何数一个data的行列数 解决:使用nrow 计算行数,使用ncol 计算列数 nrow(dat) #计算行数 ncol(dat) #计算列数
- R语言学习记录之安装caret包与jupyter关联R内核
1.安装caret包 #以下是caret包所依赖的所有包,可以用如下脚本进行安装预先依赖包 caret_needed_packages <- c("ps","pro ...
- R语言学习记录:proc.time、Sys.time函数
在R中,获得时间的函数有不少,比如Sys.time().proc.time()等. proc.time() proc.time用于获取R语言软件到当前时刻的打开时间,可以用于统计某个程序的运行时间. ...
- R语言学习记录:主成分分析的R实现
时间: 2018-08-09 教程:知乎:Learn R | 数据降维之主成分分析(上).Learn R | 数据降维之主成分分析(下) 作者:Jason 数据来源:<应用多元统计分析> ...
- R语言学习记录:聚类分析的R实现
时间: 2018-08-04 参考教程: Learn R | 统计建模之聚类分析(上). Learn R | 统计建模之聚类分析(下) 学习内容:聚类分析的R实现 数据来源:<应用多元统计分析& ...
- R语言学习记录:unique()函数
unique主要是返回一个把重复元素或行给删除的向量.数据框或数组. 向量 x <- c(3:5, 11:8, 8:11) [1] 3 4 5 11 10 9 8 8 9 10 11 uniqu ...
- r语言 c 函数返回值,R语言入门 输出函数 cat、print、paste等区别理解
一. 简介 cat.print函数都是输出函数 > cat("hello world") hello world >> print("hello wor ...
- 概率图模型基于R语言(一)贝叶斯模型
概率图模型基于R语言[一]贝叶斯模型 条件概率 贝叶斯模型 R 参考书:<概率图模型基于R语言> 记录一些代码和自己的想法和目前版本代码的写法(书中有一些无法用了) 随时更新 条件概率 熟 ...
- R语言dplyr包使用group_by函数、arrange函数和filter函数获取每个分组的第一个、第N个、最后一个记录实战
R语言dplyr包使用group_by函数.arrange函数和filter函数获取每个分组的第一个.第N个.最后一个记录实战 目录
最新文章
- thinkphp 视图(二)变量输出、赋值和替换
- 运营商部署4.5G热情高涨:将影响5G商用
- android itool 备份,教您如何将Android SMS导入iPhone
- java gridout_GridBagLayout 布局 的行列概念以及gridx,gridy失效?
- 自考计算机非笔试英语怎么考,自考中的非笔试课程是什么,怎么进行考核?
- thikPHP框架部署
- 博文视点大讲堂第20期——Windows 7来了
- 3-unit2 高级网络配置
- Linux Entering rescue mode
- 亲属关系--并查集训练T1
- 如何找回被删除的文件
- 利用sublime text进行文本对比,替换收费的sublimemerge插件
- 2012蓝桥杯【初赛试题】手机尾号
- 嵌入式系统开发笔记89:认识AVR微控制器系统架构
- HMI-43-【节能模式】顶部标题栏和底部信息栏及灯光及启动动画
- 万卷书 - 研究巴菲特 [Buffettology]
- bzero和memset函数区别联系
- 如何判断电脑是否被黑客入侵
- 凉宫春日的忧郁第一章
- 省市的json格式数据