17. R编程(三:运算符、控制语句、基本函数)
部分内容参见:生信技能树 课程
1. 运算符
关系运算符
关系正确返回TRUE
否则FALSE
== 相等 != 不相等>
大于<
小于 ps:字母多的字符串比少的大
★= 大于等于 <= 小于等于”
也可以进行向量的比较,向量中数据一一比较,若条件符合则返回TRUE
。
逻辑运算符
ps:通过tail(),head() 获取数据中的某个信息。
linkedin <- c(16, 9, 13, 5, 2, 17, 14)
last <- tail(linkedin, 2)
# 获得向量中最后两个元素
start <- head(linkedin, 2)
# 获得向量中开始的两个元素
|
表示 或,只有一个条件成立就返回真&
表示 与,必须所有条件均满足才返回真
2. if 条件语句
if 基本句
只要if 随后的条件句返回为TRUE,则其后的语句则会被执行。
i = -1
if (i<0) print('up')
if (i>0) print('up')
> i = -1
> if (i<0) print('up')
[1] "up"
> if (i>0) print('up')
if 完全表达(多条件)
if/else if/else 句 需要注意的是,无论是if 还是else if,其随后的条件句只能返回一个逻辑值(不可以是逻辑值向量)。
Warning message:
In if (x > 0) { :
the condition has length > 1 and only the first element will be used
当满足 if,执行if,当不满足if,看是否满足else if,以此类推... 最后都不符合的条件,执行else 语句。
if (condition1) {
expr1
} else if (condition2) {
expr2
} else if (condition3) {
expr3
} else {
expr4
}
tips:else 和 else if 和if 的末尾花括号在同一个位置。
ifelse 语句
ifelse
包含三个参数。条件句(返回逻辑值),yes(逻辑值TRUE返回结果),no(逻辑值FALSE 返回结果)。
> x=rnorm(10)
> x
[1] 1.19962285 -0.47281555 -0.55231510 -0.30625073
[5] 0.29614962 1.22719717 1.55893876 0.02546322
[9] 0.07590546 -0.16473795
> y=ifelse(x>0,"+","-") # x大于0返回+,小于0返回-
> y
[1] "+" "-" "-" "-" "+" "+" "+" "+" "+" "-"
而由此也可见ifelse 中的条件句,其结果可以是一个逻辑值的向量。而借助ifelse这一功能,我们便可以把复杂的字符串向量通过函数转换为对应的逻辑值向量(按照自定义的筛选),再转换为自定义的分类。
x <- "The birch canoe slid on the smooth planks"
x2 <- str_split(x, ' ')[[1]] %>%
str_to_lower()
ifelse(str_detect(x2, 't'), 'tumor','normal')
[1] "tumor" "normal" "normal" "normal" "normal" "tumor"
[7] "tumor" "normal"
3. switch 条件句
switch 用于条件句的选择执行。
switch(EXPR, ...)
...
表示各种与 EXPR
可能输出值的绑定语句。当... 中的某个丛句与EXPR值相等时,便会输出丛句对应的值。因此switch 常用于for 循环的遍历打印。
switch(EXPR = aa,
#EXPR = "aa",
aa=c(3.4,1),
bb=matrix(1:4,2,2),
cc=matrix(c(T,T,F,T,F,F),3,2),
dd="string here",
ee=matrix(c("red","green","blue","yellow")))
如果EXPR 的值与aa,bb 等不相等,则按照EXPR 顺序选择(比如aa 等于5,则返回第五个ee 对应的值)。如果均不满足,则不反回任何内容。
4. while 循环
只要condition 为TRUE,则永远执行expr 中的语句。
while (condition) {
expr
}
break 终止循环
break 直接跳出while 语句。
# Initialize the speed variable
speed <- 88
while (speed > 30) {
print(paste("Your speed is", speed))
# Break the while loop when speed exceeds 80
if (speed > 80 ) {
break
}
if (speed > 48) {
print("Slow down big time!")
speed <- speed - 11
} else {
print("Slow down!")
speed <- speed - 6
}
}
5. repeat 循环
#注意:必须有break
i=0L
s=0L
i
repeat{
i = i + 1
s = s + i
print(c(i,s))
if(i==50) break
}
6. for 循环
for 循环的两种表示
# loop version 1
primes <- c(2, 3, 5, 7, 11, 13)
for (p in primes) {
print(p)
}
# loop version 2
primes <- c(2, 3, 5, 7, 11, 13)
for (i in 1:length(primes)) {
print(primes[[i]])
}
ps:for循环中对向量取值,建议使用 [[]]
,即 [[i]]
替换 [i]
。虽然后者也没有什么问题。
对列表循环
对于list 类型变量来说使用for 循环打印元素需要注意
for (i in 1:length(nyc)){
print(nyc[[i]])
}
# 需要写[[]]
# 单个[] 会打印list 中各个类型变量
#打印结果
"""
[1] 8405837
[1] "Manhattan" "Bronx" "Brooklyn" "Queens"
[5] "Staten Island"
[1] FALSE
"""
for (i in 1:length(nyc)){
print(nyc[i])
}
# 打印结果
'''
$pop
[1] 8405837
$boroughs
[1] "Manhattan" "Bronx" "Brooklyn" "Queens"
[5] "Staten Island"
$capital
[1] FALSE
'''
嵌套循环
利用for循环遍历打印矩阵中元素
# The tic-tac-toe matrix ttt has already been defined for you
# define the double for loop
for (i in 1:nrow(ttt)) {
for (j in 1:ncol(ttt)) {
print(paste("On row", i , "and column", j, "the board contains", ttt[i, j]))
}
}
ps: paste 函数用于打印字符串与变量组合在一起。
break 和 next
在循环语句中可以通过break 与next 语句跳出循环。不过二者存在区别。next:跳过循环语句中的剩余内容,直接跳到下一次循环开始。进行中的循环结束,迭代继续。break:直接跳出循环。停止迭代,结束循环。
x <- c(5,6,0,3)
s = 0
for (i in 1:length(x)){
s=s+x[[i]]
#if(i == 3) next
#if (i == 3) break
print(c(i,x[[i]],1/i,s))
}
保存循环结果
使用print,我们可以将循环的相关变量打印出来。但可不可以保存它们?我们可以创建一个空列表,让每次循环输出的值作为一个元素添加到列表中。使用 do.call
语句我们可以对列表进行 cbind
,将其拼接在一起。
x <- c(5,6,0,3)
s = 0
result = list()
for(i in 1:length(x)){
s=s+x[i]
result[[i]] = c(i,x[i],1/i,s)
}
do.call(cbind,result)
[,1] [,2] [,3] [,4]
[1,] 1 2.0 3.0000000 4.00
[2,] 5 6.0 0.0000000 3.00
[3,] 1 0.5 0.3333333 0.25
[4,] 5 11.0 11.0000000 14.00
7. 函数
形参与实参
image.png
使用内置函数
使用函数可以按照顺序或名称调用。如sd(x, na.rm = FALSE) 通过位置
sd(values, TRUE)
通过名称
sd(x = values, na.rm = TRUE)
好用的tips:args()
可以不用像help()一样阅读大量内容,获得function的表达式。help()
与?function_name
可以获取函数使用记载的详细文件。如
> args(strsplit)
function (x, split, fixed = FALSE, perl = FALSE, useBytes = FALSE)
NULL
定义一个函数
范例
my_fun <- function(arg1, arg2) {
body
}
如定义一个计算绝对值加和的函数
sum_abs <- function(a, b){
abs(a) + abs(b)
}
# 调用函数
# sum_abs(-3, 2)
# 返回5
也可以定义不需要任何输入值的函数,直接调用 在function中不设定参数
hello <- function(){
print("Hi there!")
TRUE
}
hello()
★function 中定义的变量为局部变量,因此只能在函数内调用,在外部调用会显示无目标值。”
★变量被函数调用后发生的变化只会发生在返回值上,而变量本身数值不变。即通过某个函数计算某变量,该变量本身数值并不会改变。”
使用函数
当一个代码需要重复使用三次及以上,就该考虑使用函数或者循环。
test=iris
g <- function(i){
plot(test[,i],col=test[,ncol(test)])
}
g(1)
g(2)
g(3)
练习题
6
#练习6-3
rm(list=ls())
library(stringr)
library(tidyverse)
#1.使用循环,查看"a",TRUE和3的数据类型
# 坑:不同类型的数据只有列表可以存放。
for (i in list("a",TRUE,3)){
print(i)
print(class(i))
}
#2.生成10个随机数,根据这10个随机数生成一个新向量,>中位数的值对应"A",<中位数的值对应"B"。
t1 <- rnorm(10)
t2 <- ifelse(t1>median(t1), "A", "B")
#3.根据上一练习题中的tmp2生成一个新向量,含有e的值对应"A",不含有e的值对应"B"
tmp = "Bioinformatics is a new subject of genetic data collection,analysis and dissemination to the research community."
tmp2 = tmp %>%
str_replace(","," ") %>%
str_remove("[.]") %>%
str_split(" ")
tmp2 = tmp2[[1]]
tmp3 <- ifelse(str_detect(tmp2, "e"),"A", "B")
#4.加载deg.Rdata,根据a、b两列的值,按照以下条件生成向量x:
#a<1 且b<0.05,则x对应的值为down;
#a>1 且b<0.05,则x对应的值为up;
#其他情况,x对应的值为no
load("deg.Rdata")
x1 <- (deg$a<1)&(deg$b<0.05)
x2 <- (deg$a>1)&(deg$b<0.05)
x <- ifelse(x2, "up", ifelse(x1, "down", "no"))
# 5.统计x的重复值个数
table(x)
sum(table(x))
# 6.将x添加到deg数据框中,成为新的一列
deg <- mutate(deg, x)
load("deg.Rdata")
deg <- cbind(deg,x)
load("deg.Rdata")
deg$x <- x
#练习6-4 :
#1.使用循环,对iris的1到4列分别画点图(plot)
rm(list=ls())
str(iris)
for (i in 1:4){
plot(iris[,i], col = iris[,5])
}
#2.生成一个随机数(rnorm)组成的10行6列的矩阵,
#列名为sample1,sample2….sample6,行名为gene1,gene2…gene10,
#分组为sample1、2、3属于A组,sample4、5、6属于B组。
#用循环对每个基因画ggplot2箱线图。
x <- matrix(rnorm(60),nrow=10)
View(x)
colnames(x) <- c(paste0("sample",1:6))
rownames(x) <- c(paste0("gene",1:10))
t_x <- t(x)
group <- rep(c('A','B'), each = 3)
t_x <- data.frame(t_x)
t_x_group <- mutate(t_x, group)
# 画图
# 发现ggplot 并不能像基础包直接循环绘图,查询后尝试先用list存储,
# 参考:https://blog.csdn.net/weixin_33963594/article/details/89616215
# 再拼图
library(ggplot2)
library(patchwork)
list_plot = list()
for (i in 1:10){
list_plot[[i]] <- ggplot(data=t_x_group,
aes_string(x='group', y=colnames(t_x_group)[i])) +
geom_boxplot(aes(color = group))
}
wrap_plots(list_plot, nrow = 2,guides = "collect")
dev.off()
# 彩蛋提示,发现还可以用长窄的gather 数据框结合分面完成。
x <- matrix(rnorm(60),nrow=10)
View(x)
colnames(x) <- c(paste0("sample",1:6))
rownames(x) <- c(paste0("gene",1:10))
t_x <- t(x)
group <- rep(c('A','B'), each = 3)
t_x_group <- cbind(t_x, group)
t_x_group <- data.frame(t_x_group)
x_gather <- gather(data = t_x_group, key=gene, value=exp, - group)
x_gather$exp <- as.numeric(x_gather$exp)
# 作图
library(ggplot2)
ggplot(data=x_gather) +
geom_boxplot(aes(x=group, y=exp, color=group)) +
facet_wrap(~gene, ncol = 5)
# 发现gene10 会排在gene1后面。未来可以进一步解决。
相关文章
- 【技术种草】cdn+轻量服务器+hugo=让博客“云原生”一下
- CLB运维&运营最佳实践 ---访问日志大洞察
- vnc方式登陆服务器
- 轻松学排序算法:眼睛直观感受几种常用排序算法
- 十二个经典的大数据项目
- 为什么使用 CDN 内容分发网络?
- 大数据——大数据默认端口号列表
- Weld 1.1.5.Final,JSR-299 的框架
- JavaFX 2012:彻底开源
- 提升as3程序性能的十大要点
- 通过凸面几何学进行独立于边际的在线多类学习
- 利用行动影响的规律性和部分已知的模型进行离线强化学习
- ModelLight:基于模型的交通信号控制的元强化学习
- 浅谈Visual Source Safe项目分支
- 基于先验知识的递归卡尔曼滤波的代理人联合状态和输入估计
- 结合网络结构和非线性恢复来提高声誉评估的性能
- 最佳实践丨云开发CloudBase多环境管理实践
- TimeVAE:用于生成多变量时间序列的变异自动编码器
- 具有线性阈值激活的神经网络:结构和算法
- 内网渗透之横向移动 -- 从域外向域内进行密码喷洒攻击