写在表面: R萌新请自行恶补,本文的初衷是自己记录心路历程并且对有基础的同好能相互讨论,彼此激励。不排除写着写着,变成科普,尽力保持门槛。喜则阅,不喜勿喷。耐受催更,不定时答疑 :)。
第二日:没人发现他存在 多自由自在
1.过程控制
1.1 循环
1.2 条件
2.自定义函数
3.基础画图工具
3.1 散点图
3.2 柱状图
3.3 饼图
我们这次聊聊R语言的过程控制,说到编程语言(本人的心得)其实差不多都一样。无非是变量类型和过程控制,当然各种语言有自己的的优势,譬如python和perl处理字符相当有一套,R处理数组的方法既多又好理解。所以就是各有所长,但是对于过程的控制大抵思想是一样的。
1.过程控制
1.1 循环
循环很好理解,其实就是对一个操作的重复,这个重复可能不是简单的重复,可能在重复的过程中还有外部变量的传递和改变,或者就是一个内部变量的累积。和大多数语言类似,R这里面的循环主要包括for和while语句。另外对数组矩阵等高级一点的操作,比如说 apply系列,诸如vapply, lapply, sapply 等。
for,while循环
这个直接上例子不解释。
# for 循环
for(i in c(1:20)){
print(i)
}
# while循环
while(i <= 10){
print(i)
i=I+1
}
这里面我想说的就是,R的语言没有那么强的仪式感。怎么说呢,像python这样的属于格式敏感的语言,空格和tab的多少会影响过程的走向。虽然R没有这么多格式的要求,但是我们在写R的时候也尽量遵循着格式,毕竟好的格式安排还是能很好读懂的。
apply系列博大精深,而且骚气的操作颇多。这里面只是对其基本的操作进行下介绍。apply()是个函数,这个函数接受三个主要的变量,首先是 一个二维矩阵。
举个🌰:
> mat1 <- c(1:12)
> dim(mat1) <- c(3:4)
> print(mat1)
[,1] [,2] [,3] [,4]
[1,] 1 4 7 10
[2,] 2 5 8 11
[3,] 3 6 9 12
如果我想求每一行的和,
m=c()
for (i in 1:nrow(mat1)){
m[i] <- sum(mat1[I,])
}
print(m)
#
[1] 22 26 30
显然我们要写很多行,而且每一步人顾及的事情太多。如果不是简单的加和还有别的任务就显得更加麻烦。所以这里面我们应用apply这个函数,就能让我们的注意力专注在加和这件事情上。
m <- apply(mat1,1,sum )
上面这个apply里,我们把矩阵给定,然后第二位的数字1表示按行操作,2表示按列操作,而我们专注的事情在每一列操作的步骤,就是 sum。
下面可以再看看其他循环的函数。
> x <- list(a = 1:10, beta = exp(-3:3), logic = c(TRUE,FALSE,FALSE,TRUE))
> # 为每一个列表计算平局值
> lapply(x, mean)
$a
[1] 5.5
$beta
[1] 4.535125
$logic
[1] 0.5
> rbind(lapply(x, mean))
a beta logic
0% 1.00 0.04978707 0.0
25% 3.25 0.25160736 0.0
50% 5.50 1.00000000 0.5
75% 7.75 5.05366896 1.0
100% 10.00 20.08553692 1.0
> rbind.data.frame(lapply(x, mean))
a beta logic
0% 1.00 0.04978707 0.0
25% 3.25 0.25160736 0.0
50% 5.50 1.00000000 0.5
75% 7.75 5.05366896 1.0
100% 10.00 20.08553692 1.0
> # median and quartiles for each list element
> lapply(x, quantile, probs = 1:3/4)
$a
25% 50% 75%
3.25 5.50 7.75
$beta
25% 50% 75%
0.2516074 1.0000000 5.0536690
$logic
25% 50% 75%
0.0 0.5 1.0
> sapply(x, quantile)
a beta logic
0% 1.00 0.04978707 0.0
25% 3.25 0.25160736 0.0
50% 5.50 1.00000000 0.5
75% 7.75 5.05366896 1.0
100% 10.00 20.08553692 1.0
1.2 条件
先上例子
# If 语句
I <- 1
if(i == 1){
print("Hello World")
}
[1] "Hello World"
# If-else 语句
I <- 2
if(i == 1){
print("Hello World!")
}else{
print("Goodbye World!")
}
[1] "Goodbye World!"
# switch 选择语句
# switch(expression, cnoditions)
products = c("denovo", "reseq")
for (i in feelings){
print(
switch(i,
tr = "转录调控",
reseq = "重测序",
denovo = "从头组装",
other = "其他"
)
)
)
[1] "从头组装"
[1] "重测序"
2.自定义函数
上面咱们提到了过程控制。我们如果从头到尾都用过程的话,长度会很长。有很多过程可能会 repeat,这样虽然读起来很好懂,单无疑增加了文件的体积而且也更容易出错,我们编程的思想首先是面向对象,让对象自己管理方法和函数。但是在这之前,我们要做的还有尽量精简代码,把方法变成小段模块方便调用。这就要用到函数这个功能。
像上面那个switch的🌰。我们可能要在很多地方用的这个方法。所以就把它封装成函数。
product = function(x){
for (i in x){
print(
switch(I,
tr = "转录调控",
reseq = "重测序",
denovo = "从头组装",
other = "其他"
)
)
}
}
products = c("denovo", "reseq")
product(products)
[1] "从头组装"
[1] "重测序"
3.基础画图工具
3.1 散点图
散点图,其实就是由一些散乱的点组成的图表,这些点其实一点也不散乱,事实上这些点在哪个位置,是由其x值和y值确定的。我们绘制散点图,会比表格展示更有趋势和意义。
dotchart(mtcars$mpg,
labels=row.names(mtcars),cex=0.7,
main="Gas Mileage for Car Models",
xlab="Miles Per Gallon")
3.2 柱状图
表现为柱子的图有两种,barplot和histogram。
histogram: a diagram consisting of rectangles whose area is proportional to the frequency of a variable and whose width is equal to the class interval.
Bar chart: a graph consisting of rectangular bars. There bars actually represents number or percentage of observations of existing categories in a variable. The height of bars gives a visual representation of the proportional differences among categories.
朴素的讲:histogram用来描述的是numerical变量,而bar plot用来描述的是categorical类型的变量。
print(u)
201909 201910 201911 201912 202002 202003 202004
a 0 0 0 0 0 7 4
b 0 0 0 0 1 46 12
c 0 0 0 0 1 4 0
d 0 0 0 0 4 12 0
e 0 0 0 0 0 1 0
f 0 5 1 1 6 226 75
g 1 0 1 1 1 1 0
barplot(u,legend.text = row.names(u),col = rainbow(7),args.legend = list(x = "topleft"))
barplot(u,legend.text = row.names(u),col = rainbow(7),args.legend = list(x = "topleft"),beside = T)
3.3 饼图
print(k)
a b c d e f
11 59 5 16 1 5
pie(k,border = 4)