本文是笔者近期使用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_manualscale_size_manualscale_shape_manualscale_linetype_manualscale_alpha_manualscale_discrete_manual等。以scale_fill_manual函数为例,从其名字上就可以看出,该函数可以手动设置填充色。

ggplot2 修改坐标轴

修改坐标轴主要用到scale_x_continuousscale_y_continuousscale_x_discretescale_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)相关推荐

  1. R语言小白记录1:如何数一个data的行列数

    小白开始记录自己的R语言学习过程. 遇到的问题:如何数一个data的行列数 解决:使用nrow 计算行数,使用ncol 计算列数 nrow(dat) #计算行数 ncol(dat) #计算列数

  2. R语言学习记录之安装caret包与jupyter关联R内核

    1.安装caret包 #以下是caret包所依赖的所有包,可以用如下脚本进行安装预先依赖包 caret_needed_packages <- c("ps","pro ...

  3. R语言学习记录:proc.time、Sys.time函数

    在R中,获得时间的函数有不少,比如Sys.time().proc.time()等. proc.time() proc.time用于获取R语言软件到当前时刻的打开时间,可以用于统计某个程序的运行时间. ...

  4. R语言学习记录:主成分分析的R实现

    时间: 2018-08-09 教程:知乎:Learn R | 数据降维之主成分分析(上).Learn R | 数据降维之主成分分析(下) 作者:Jason 数据来源:<应用多元统计分析> ...

  5. R语言学习记录:聚类分析的R实现

    时间: 2018-08-04 参考教程: Learn R | 统计建模之聚类分析(上). Learn R | 统计建模之聚类分析(下) 学习内容:聚类分析的R实现 数据来源:<应用多元统计分析& ...

  6. R语言学习记录:unique()函数

    unique主要是返回一个把重复元素或行给删除的向量.数据框或数组. 向量 x <- c(3:5, 11:8, 8:11) [1] 3 4 5 11 10 9 8 8 9 10 11 uniqu ...

  7. r语言 c 函数返回值,R语言入门 输出函数 cat、print、paste等区别理解

    一. 简介 cat.print函数都是输出函数 > cat("hello world") hello world >> print("hello wor ...

  8. 概率图模型基于R语言(一)贝叶斯模型

    概率图模型基于R语言[一]贝叶斯模型 条件概率 贝叶斯模型 R 参考书:<概率图模型基于R语言> 记录一些代码和自己的想法和目前版本代码的写法(书中有一些无法用了) 随时更新 条件概率 熟 ...

  9. R语言dplyr包使用group_by函数、arrange函数和filter函数获取每个分组的第一个、第N个、最后一个记录实战

    R语言dplyr包使用group_by函数.arrange函数和filter函数获取每个分组的第一个.第N个.最后一个记录实战 目录

最新文章

  1. thinkphp 视图(二)变量输出、赋值和替换
  2. 运营商部署4.5G热情高涨:将影响5G商用
  3. android itool 备份,教您如何将Android SMS导入iPhone
  4. java gridout_GridBagLayout 布局 的行列概念以及gridx,gridy失效?
  5. 自考计算机非笔试英语怎么考,自考中的非笔试课程是什么,怎么进行考核?
  6. thikPHP框架部署
  7. 博文视点大讲堂第20期——Windows 7来了
  8. 3-unit2 高级网络配置
  9. Linux Entering rescue mode
  10. 亲属关系--并查集训练T1
  11. 如何找回被删除的文件
  12. 利用sublime text进行文本对比,替换收费的sublimemerge插件
  13. 2012蓝桥杯【初赛试题】手机尾号
  14. 嵌入式系统开发笔记89:认识AVR微控制器系统架构
  15. HMI-43-【节能模式】顶部标题栏和底部信息栏及灯光及启动动画
  16. 万卷书 - 研究巴菲特 [Buffettology]
  17. bzero和memset函数区别联系
  18. 如何判断电脑是否被黑客入侵
  19. 凉宫春日的忧郁第一章
  20. 省市的json格式数据

热门文章

  1. 结构变异( SV )分析介绍
  2. 31 | SpringBoot安全之整合Spring Security
  3. OpenCV双目鱼眼相机标定
  4. 名创优品营收增速再下降:年收入和豪言还差900亿,高瓴抄底失败
  5. 用户画像数据指标体系之用户消费维度
  6. cindy java_Cindy User Guide
  7. Linux调度器及CFS调度器
  8. 计算机网络的标准化工作与相关组织
  9. Graphviz 双向边和无向边
  10. jdk小工具jps介绍 - Sky's blog - BlogJava