因为自己之前学习过一部分B站生信技能树的R语言入门视频,但实际使用时经常会遇到一些问题,这次参加了生信技能树的系统培训班想查漏补缺。这里是整理的第一周学习笔记,主要是针对以前存在的一些问题有了更清晰的认识。
一、基本概念
R语言中有三种数据类型,分别是数值型(numeric),字符型(character),逻辑型(logical)
R语言中有四种主要的数据结构,分别是向量(vector),数据框(data.frame),矩阵(matrix)和列表(list)。其中用于生信分析最重要的两种数据结构是向量和数据框,需要重点掌握。
向量的创建方式:以函数c为基本方式,纯数值型向量可通过n:m创建。创建字符型向量只能用c。一个向量中只能有一种数据类型,优先级为:character>numeric>logical。多个类型的数据类型存在时,向量会自动定义为优先级最高的数据类型。
代码语言:javascript复制a=c(1,2,3,4,5,6)
a=1:6
a=c('Gene','Expression','Group')
d=c('Gene',6); e=c('Gene',True), f=c(6,True)
class(d); class(e); class(f)
数据框中,每一列的所有数据只有一种数据类型,不同列的数据类型可不相同。
代码语言:javascript复制df1 <- data.frame(gene = paste0("gene",1:4),
change = rep(c("up","down"),each = 2),
score = c(5,3,-2,-4))
df1
矩阵和数据框类似,但整个矩阵只存在唯一的一种数据类型,在生信分析比数据框应用少。
二、循环补齐
比较下列代码:
代码语言:javascript复制> paste0('x',1:3)
[1] "x1" "x2" "x3"
> paste0(rep('x',2),1:3)
[1] "x1" "x2" "x3"
> paste0(rep('x',3),1:3)
[1] "x1" "x2" "x3"
> paste0(rep('x',8),1:3)
[1] "x1" "x2" "x3" "x1" "x2" "x3" "x1"
[8] "x2"
当两个向量进行等位运算时(目前学习到的有==,paste(0),加减乘除),如果向量长度不等,R语言会自动发生循环补齐,即重复较短的向量,直到它与另一个向量长度相等。
小Tips:paste和paste0的区别:
代码语言:javascript复制> paste0('x',1:3)
[1] "x1" "x2" "x3"
> paste('x',1:3)
[1] "x 1" "x 2" "x 3"
paste内置了sep='',有空格;paste0(x,y)相当于paste(x,y,sep='')
三、取向量或数据框元素
取元素有两种方法:通过等长的逻辑向量,或通过具体的下标索引。
代码语言:javascript复制#向量
> a=c('a1','a2','a3','a4','a5','a6')
> b=c(T,T,F,T,F,F)
> a[b]
[1] "a1" "a2" "a4"
> a[c(1,2,4)]
[1] "a1" "a2" "a4"
#数据框
> df=data.frame(a=1:5,b=6:10,d=11:15)
> df
a b d
1 1 6 11
2 2 7 12
3 3 8 13
4 4 9 14
5 5 10 15
> df[5,]
a b d
5 5 10 15
> df[,2]
[1] 6 7 8 9 10
> df[,'b']
[1] 6 7 8 9 10
> df[4,3]
[1] 14
> df$a
[1] 1 2 3 4 5
> df$a[c(T,F,T,T,F)]
[1] 1 3 4
思考题
代码语言:javascript复制> x=rnorm(10)
> x
[1] 0.08543185 -0.07857707 0.99107596 1.46106966
[5] -0.76300231 -0.67211279 1.14260556 -0.37063542
[9] 0.65229441 0.69052127
> sort(x[x<0])
[1] -0.76300231 -0.67211279 -0.37063542 -0.07857707
> sort(x)[x<0]
[1] -0.67211279 0.08543185 0.65229441 0.99107596
两句代码都能运行,第一个比较容易理解,就是向量x中小于0的元素按从小到大排序;
第二个比较难理解,可以y=sort(x),z=【x<0】(这里英文中括号显示不出来,用了中文中括号代替)
y是x排序后新得到的一个向量,里面的元素都是numeric;而z是对x中的元素依次进行是否小于0的判断,最后得到的也是一个向量,里面的元素是True或者是False的logical;所以当y【x】的时候,本质上就是对y这个新向量按逻辑值取子集,因此是有结果的。
四、合并向量或数据框
1、合并两个向量
代码语言:javascript复制> x=c('a','a','a')
> y=c('b','b','b')
> paste0(x,y)
[1] "ab" "ab" "ab"
> c(x,y)
[1] "a" "a" "a" "b" "b" "b"
2、合并两个数据框
代码语言:javascript复制> test1 <- data.frame(name = c('jimmy','nicker','Damon','Sophie'),
blood_type = c("A","B","O","AB"))
> test1
name blood_type
1 jimmy A
2 nicker B
3 Damon O
4 Sophie AB
> test2 <- data.frame(name = c('Damon','jimmy','nicker','tony'),
group = c("group1","group1","group2","group2"),
vision = c(4.2,4.3,4.9,4.5))
> test2
name group vision
1 Damon group1 4.2
2 jimmy group1 4.3
3 nicker group2 4.9
4 tony group2 4.5
> test3 <- data.frame(NAME = c('Damon','jimmy','nicker','tony'),
weight = c(140,145,110,138))
> test3
NAME weight
1 Damon 140
2 jimmy 145
3 nicker 110
4 tony 138
> merge(test1,test2,by="name")
name blood_type group vision
1 Damon O group1 4.2
2 jimmy A group1 4.3
3 nicker B group2 4.9
> merge(test1,test3,by.x = "name",by.y = "NAME")
name blood_type weight
1 Damon O 140
2 jimmy A 145
3 nicker B 110
merge函数是合并数据框最常用的函数,by.x和by.y两个形式参数定义根据哪一列进行合并。如果是根据行名合并,可使用cbind函数。可参考我的dataframe练习:https://cloud.tencent.com/developer/article/2238411?areaSource=&traceId=
五、%in%
1、%in%和==的区别:==是将X中的每个元素和y中的每个元素一对一比较,%in%是将x中的每一个元素分别和y中的所有元素全部比较
代码语言:javascript复制> x=c(1,3,5,1)
> y=c(3,2,5,6)
> x==y
[1] FALSE FALSE TRUE FALSE
> x%in%y
[1] FALSE TRUE TRUE FALSE
> y%in%x
[1] TRUE FALSE TRUE FALSE
2、应用==,!=,|进行比较运算时,可直接用%in%代替。
代码语言:javascript复制test=data.frame(
paste0("gene",1:12),
change=rep(c("up","down"),each=6),
Species=rep(c('a','b','c'),4)
)
#选择其中species为a或c的行
x=test[test$Species!='b',]
x=test[!test$Species=='b',]
x=test[test$Species=='a'|test$Species=='c',]
x=test[test$Species%in%(c('a','c')),]
#错误答案:
test[test$Species==c('a','c'),]#会发生循环补齐
test[test$Species=='a'|'c',]#会报错
示例可见我的dataframe练习:https://cloud.tencent.com/developer/article/2238411?areaSource=&traceId=
当变量很多时,%in%是唯一的解决办法。
3、%in%和intersect的区别:%in%不会去重复,而intersect会去重
代码语言:javascript复制 > a
[1] "COMMD1" "COMMD1" "CCT4" "AC017081.1"
[5] "RAB7A" "CCT4" "ZDHHC16" "CASKIN2"
[9] "MYL12B" "GGT7" "SNRPE"
> b
[1] "NYNRIN" "CECR5" "RAB7A" "FO538757.2"
[5] "COMMD1" "C10orf128" "HEPH" "HBD"
[9] "AFG3L2" "ZNF586" "SPDL1" "KLHDC8A"
[13] "AC017081.1" "SLC30A9" "CECR5" "GGT7"
[17] "COMMD1" "CASKIN2" "MPP2" "KLHDC8A"
[21] "PLEKHN1"
> table(a%in%b)
FALSE TRUE
5 6
> length(intersect(a,b))
[1] 5
由于a里有两个COMMD1,因此intersect后去除了重复的一个,所以a%in%b
中有6个True,而intersect(a,b)
只有5个。
六、一些小技巧
1、rep的妙用
代码语言:javascript复制> rep(c('a','b','c','d'),3)
[1] "a" "b" "c" "d" "a" "b" "c" "d" "a" "b" "c" "d"
> rep(c('a','b','c','d'),each=3)
[1] "a" "a" "a" "b" "b" "b" "c" "c" "c" "d" "d" "d"
2、unique和duplicated函数
unique函数得到的变量是numeric或character,而duplicated最终得到logical。
代码语言:javascript复制> x=rep(c('a','b','c','d'),each=3)
> x
[1] "a" "a" "a" "b" "b" "b" "c" "c" "c" "d" "d" "d"
> unique(x)
[1] "a" "b" "c" "d"
> duplicated(x)
[1] FALSE TRUE TRUE FALSE TRUE TRUE FALSE TRUE TRUE FALSE TRUE TRUE
在某些只能用logical的情况下,如通过logical取子集时,善用!duplicated
> x[!duplicated(x)]
[1] "a" "b" "c" "d"
3、常用内置函数
vector: letters,LETTERS
dataframe: iris, iris3
matrix: volcano
4、读取和存储
csv,table用read读,用write存;R.data用load读,用save存
读取文件有两种方式:一种用tab,一种用路径;路径可以复制粘贴,如果是在上一级的另一个文件夹中可以用../表示R.project的上一级菜单
ex2 <- read.csv("ex2.csv",row.names = 1,check.names = F)
row.names=1表示使用第一列为行名,需注意行名中不能出现重复;check.names表示保留‘-’符号;
soft2 <- read.table("soft.txt",header = T,sep = "t")
header=T表示使用第一行为列名,sep = "t"表示以tab(制表符)为分隔符
b=data.table::fread('soft.txt',data.table = F)
fread函数是一种较为智能的读文件函数,可以在日后实践中多尝试。
七、一些提示
1、as转换函数
as系列函数前后变量要统一,如z=as.data.frame(y),z,1:6=as.numeric(z,1:6),不能直接运行as系列函数,也不能前后不统一,否则会报错。
2、R语言思维
能用代码实现的不要手动去做。一些最基本的函数代替手动看/数数的方法:
1、使用length和table函数;
2、使用ncol和nrow,如取数据框b的最后一列:b[,ncol(b)]
,删除b的最后一列:b[,-ncol(b)]
3、最容易会犯的错误:忘记c、逗号(,)和引号('')
根据我这两天写代码试运行的结果来看,90%的错误会出现在忘记c,引号('')和逗号(,)这三个上面。忘记c就是忘记创建向量直接写了元素;忘记引号就是把要写的字符直接打成了变量,而变量本身不存在,所以经常会报错;忘记逗号主要是在数据框取某些行或列,只写了行或列的条件,没写逗号表示出行或列,另外就是在创建数据框的不同列时忘记用逗号分隔。所以报错的时候时常想想 c '' , 这三个,或许问题就能解决了。
写在最后
第一周的课程先结束了,今晚做了一下这周笔记的总结,希望内容能帮助到大家,有不足之处也请大家批评指正,谢谢!