r语言学习RNA-seqR小推车

R 使用笔记:日常备忘

2017-12-04  本文已影响297人  GPZ_Lab

笔记内容:

  • 使用Rstudio的快捷键及tips
  • 一些工作中常用、有用的packages及函数
  • 各种日常备忘
  • ... ...
  1. Rstudio中批量注释
    Ctrl + shift + C

  2. 把list转化为vector
    一些函数的input会要求数据格式必须为vector,比如需要将data.frame中跳出来一列(list)转化为vector, 且可以将其character分Levels,作为factor呈现。

vector = unlist(list, use.names = FALSE)
  1. 寻找重复值
duplicated()

在data.frame中寻找重复值, df[duplicated(df['ID']), ] 即返回df中ID列的重复值。duplicated()本身返回一个Logic变量。

  1. ggrepel在使用ggplot画图中的应用
    有时候画图plot上很多点,每个点都要加label或者text,密集的地方就都挤在一起看不清谁是谁。如果使用ggplot画图,可以使用ggrepel中的geom_text_repel(),简单的+ggplot()后面即可
install.packages('ggrepel')
library(vegan)
library(ggrepel)
mds <- cmdscale(unifrac, k=2)
mds_df <- data.frame(mds)   # ggplot 只接受dataframe
ggplot(mds) + 
  geom_point(aes(mds_df['X1'], mds_df['X2'] )) + 
  geom_text_repel(aes(aes(mds_df['X1'], mds_df['X2']), label = row.names(mds_df))

如上图所示,label之间就可以互相隔开不重叠,且还有折线把label指向相应的点。
详情可以参考这个链接

  1. 连续型变量的分层(变为factor)
    有些变量(年龄数值、血糖数值等)可能在作为连续型变量时难以发现规律,但是在分层为若干个数值范围后变得有规律可循,且可以作为分类型变量使用卡方检验。

在R中将连续型变量分为若干个层次,使用cut()

d$GC.binned <- cut(d$percent.GC, 5)
#将d的percent.GC列分为均等的5个层次,且作为新的一列GC.binned加入d
cut(d$percent.GC, c(0, 25, 50, 75, 100))
#也可以这样来分为(0,25] (25,50] (50,75] (75,100] 几个level
table()
#使用table()查看每个Level有多少样本落在里面
  1. packageggplot2的强大画图功能
    ggplot2只能应用于dataframe格式的data
    它存在两种用法:
    (1)一种为geom_XXX, 作为几何学对象(geometric objects),常用于指定将input_data绘制成怎样的图。
    (2)一种即为几何学对象添加设计类属性(aesthetic attributes),如指定图的x轴y轴为data的哪些部分,指定形状,label,颜色等属性。

plot使用基本数据集d:ggplot(d)(用加号与后面的layer相连接)
plot出点,指定x和y的取值aes()
facet_wrap()facet_grid()的用法:按照一个分类变量的column,将每个level画一个图。即按照某一个column的level分层画图。

d$time_point = factor(d$time_point)
ggplot(d, aes(x, y, colour = time_point)) + geom_point()
# aes()中指定了x,y轴的取值,直接使用dataframe d中的变量名称即可。作为分组显示不同颜色的变量time_point必须首先指定为factor
  1. is.na()
    is.na(i)可以知道i中的缺失值。即为NA(not available)的值。其返回为Ture&False。使用table(is.na(i))统计i中的缺失值有多少个。
    !is.na()即查看非缺失值

  2. read.table()
    有时候直接使用read.table()读取文档,R会在column names上加上X,比方说纯数字的column names 3-1, 3-2, 3-3这样,会变成X3-1, X3-2, X3-3
    加上check.names = FALSE即可

  3. subset data.frame

bar <- subset(foo, location == "there")
foo[foo$location == "there", ] #不要忘了逗号,逗号左边subset行,右边subset列
  1. 把data.frame中的两列string, 合并为一列,并以指定连接符连接: paste
meta$detail <- paste(meta$sample_position,meta$treatment, sep = '_')
# meta中sample_position与treatment两列以下划线连接起来,成为新列detail
  1. 在linux系统上install.packages()的问题
    有时候因为R版本不够新或者linux系统的各种问题,不能像windows那样直接用install.packages()安装需要的包。
    比如说“devtools”,一个“可以让你install别人在github上做的包”的包:
    先更新一下r-base:
    $ sudo apt-get update
    $ sudo apt-get install r-base
    如果返回说“r-base is already the newest version(...)”, 那说明安装不上包不是R版本太旧的原因。
    google一下发现在linux上装devtools需要一些build-essential的东西:
    $ sudo apt-get install build-essential libcurl4-gnutls-dev libxml2-dev libssl-dev
    安装好了之后,用root打开R shell
    $ sudo -i R
    install.packages('devtools')
    然后会弹出来让你选择安装来源的窗口,选择0-Cloud
    ....装好了,可以打开R studio, library('devtools')就可以使用了
    参考这个链接

  2. 使用brewer.pal,rainbow(),colorRampPalette调色作图
    RColorBrewer是很棒的调色板包,它的好处在提供各种服务于各种不同类型的数据(有序离散型,无序离散型,连续型变量等),用颜色的深浅表现循序渐进的关系。色彩饱和度较低不刺眼,又可以显著区分的颜色区分数据中不同的类别。但也存在调色板少,调色板中颜色也太少,不能在超多变量情况下使用的问题。这个问题可以用rainbow()来解决。
    主要有以下三种调色板:
    (1)有序变量的调色板(sequential):从高到低,从小到大的数据,用从浅到深的颜色表示。需要注意的是每个调色板可用的颜色数目只有3-9个。也就是说要用不同颜色表示的类别,最少要有3个,最多只能有9个。
    (2)两极分化的调色板(divergent):在热图的图例中常见,主要关注的是数据的两极分化情况。关注变量在哪些样本中富集,在哪些样本中稀疏。需要注意的是每个调色板可用的颜色数目只有3-11个
    (3)无序分类的调色板(qualitative):各类之间地位等同,没有顺序之分。需要注意的是每个调色板可用的颜色数目根据不同的Set有着不同的颜色上限,其下限均为3个,上限最高的为12个。
    顺便一提Pastel1Pastel2这两个调色盘颜色饱和度很低,可以说是马卡龙色和莫兰迪色了;Set1,Set2,Set3这三个调色盘颜色饱和度从高到低。
    Paired调色板一半为冷色调一半为暖色调,可以为分为两类,又细分为若干小类的数据绘图,十分实用。

# 用display查看想用什么颜色,看帮助文档,有各种各样的set可供使用
display.brewer.pal(8, 'Blues')
display.brewer.pal(8, 'BrBG')
display.brewer.pal(8, 'Set3')
display.brewer.pal(8, 'Paired')

rainbow虽说在帮助文件中说是为生成一系列连续型变量,但在超多变量或样本的数据中,为类别着色也十分管用。比如给80个样本绘制rarefaction curve, 可以用rainbow生成80个不同的颜色。

col_rainbow <- rainbow(80, s=0.8, v=1)
# 80代表要生成的颜色数量,参数s和v用于设置颜色的饱和度

colorRampPalette使用方法:

colorcount <- length(unique(colnames(tax_ra)))  # 比方说你想给tax_ra的每个column都安排一个颜色,column数量巨大
getPalette <- colorRampPalette(brewer.pal(9,"Set1"))
color <- getPalette(colorcount)
# color就是和tax_ra的column相对应起来的一众颜色了
  1. 按照factor中的levels,将levels用不同颜色区分开
    虽说应该不会忘,但是还是记录一下:
    比如要在meta这个data.frame中,按照meta$treatment这一分类变量,给样本上色。meta$treatment在这里需要转化为具有Level的factor形式。
detail <- as.factor(meta$treatment)  # 看到下面多了一行Levels: XXXX
length(levels(detail))  # 知道有多少个Levels,在Levels很多的时候可以用
plot_color <- rainbow(length(levels(detail)))[detail]  
# print plot_color可以看到detail数目的颜色代码,按照levels标记了。

col1 <- brewer.pal(4,'Set1')
plot_color <- col1[detail]
# 或者用brewer.pal, 一样的道理
  1. 你有两个data.frame,df1的列是df2的行,但是排列顺序不一样。你想用把df2 reorder成df1列的顺序。
    可是说是很拗口了,如下图所示举个例子:

如果sample的顺序可以直接正序或者倒序当然很方便,但是如果df是按照固定顺序排列的,你在某个热图中想用这种顺序展示结果。
使用match来把顺序记录下来:

df2_ <- df2[,match(rownames(df1), colnames(df2))]
##df2行的顺序就变成df1列的顺序了
  1. 在R里改dataframe的列名称(colnames)
    比方说上面的df2,要把sample4改成S4。
colnames(df2)[2] <- c('S4')     # 把第二个colname改成S4
colnames(df2)[colnames(df2) == 'Sample4'] <- "S4"    # 把名为“sample4”的改为S4
colnames(df2) <- c('x1','x2','x3'...)   # 批量修改colnames
  1. 分组求均值及标准差:mean(sd)
    data(ToothGrowth)为例
library(plyr)
ddply(t, ~supp, summarise, mean = mean(len), sd = sd(len))
# 得到:
  supp   mean   sd
1 OJ   20.66333 6.605561
2 VC   16.96333 8.266029

参考这个链接:how to summarize data by group in r

17. apply, sapply, lapply, tapply的用法
apply:
apply的适用对象可以为matrix或者dataframe, 一个有行列的数据结构。
apply(matrix, x, fun())
x可以取值为1,2,或者c(1,2), 1即行,取值为1则会对每行行使fun()函数,取值为2则对每列行使fun()函数。
在对每行每列求均值,方差等,十分有用:apply(matrix, 1, mean) # 即对matrix的每行求均值

lapply及sapply:
laapy及sapply的适用对象为List,直接Input一个dataframe, 它会把每个value当作一个list来处理,估计不会得到你想要的结果。
lapply(lists, fun())
但是dataframe$coln得到的是List,如果你想给多个列apply函数,则:
lapply(dataframe[, 1:80], fun(x) as.numeric(as.character(x)))
即对datafrmae的前80列,转化为数值型变量。这个可以用于:全部是factor的数值型变量转话为纯数值型变量(去Levels)。
sapply是lapply的参数simplify = FALSE的情况,将每个list输出结果合并成一个matrix

tapply:
适用于分组进行操作,比如分组求和,求均值方差等。类似于excel中的透视表功能。
但是需要注意它的Input是一个vector(即data.frame的一列,或者一个List),一个index(转化为factor的分组信息)。
group <- factor(dataframe$group)
gender <- factor(dataframe$gender)
tapply(dataframe[,3], list(dataframe$group, dataframe$gender), mean)
则输出一个以group和gender分组为行列的matrix, value为对应分组下的dataframe第三列value平均值。

  1. R的函数不能return超过一个对象:不能return(a, b), 怎么办?
    在function中写入:
     ...
     list <- list("name1" = a, "name2" = b)
return (list)
# 在需要使用时用$
output <- fun()
a <- output$name1
b <- output$name2
  1. linux中更新R-base
$ sudo apt-get install r-base
$ sudo apt upgrade r-base r-base-dev
$ sudo apt update
$ sudo apt upgrade
  1. 在windows系统中setwd()设置路径
    C:\Users\Usernames\Desktop\工作\项目A
    -------> C:/Users/Usernames/Desktop/工作/项目A

  2. cbind()的局限
    cbind()的output是一个matrix,这意味着它只能容忍一种类型的数据。要么全是数值型,要么全是分类型。如果你试图把一列factorcbind()到另一个dataframe上,可能会出现factor全部变成数值(level个数)的情况。这种时候还是用data.frame()
    (多么鸡肋,要你何用?=_=)
    data.frame(df1, group = df2$factor)

  3. 函数中传参数用于dataframe的切片
    如下所示,不能用dataframe$传参数切片,用dataframe[,]

test
    s1 s2 s3 s4 tax
OTU1  1  3  5  2   p
OTU2  2  2  1  1   p
OTU3  3  0  2  0   g
OTU4  4  1  1  1   g
OTU5  1  8  0  0   g
OTU6  0  0  4  2   p

test_fun <- function(dataframe, col)  {
    a = dataframe$col
    b = dataframe[col]
    c = dataframe[, col]
    return(a = a, b = b, c = c)

aa = test_fun(test, 'tax')
aa
$a
NULL

$b
    tax
OTU1   p
OTU2   p
OTU3   g
OTU4   g
OTU5   g
OTU6   p

$c
[1] p p g g g p
Levels: g p

class(aa$b)
[1] "data.frame"
class(aa$c)
[1] "factor"
  1. 去除含有NA的行(把所有带NA的都去掉)
    data <- data[complete.cases(data), ]

  2. split的用法
    split的Input可以是vector, list, data.frame,其返回值为list。split(x, f): x 为Input data, f为分层信息的数据,一般为一个factor

# split应用于vector及list,常常与lapply结合起来
lapply(split(iris$Sepal.Length, iris$Species), mean)
$`setosa`
[1] 5.006

$versicolor
[1] 5.936

$virginica
[1] 6.588

se <- iris[iris$Species == "setosa", "Sepal.Length"]
mean(se)
[1] 5.006

# split应用于data.frame,
a <- split(iris, iris$Species) # 得到一个list, 里面是按照不同species分好组的子data.frame 
sapply(a, function(x) {colMeans(x[,c("Petal.Length", "Petal.Width")])})
             setosa versicolor virginica
Petal.Length  1.462      4.260     5.552
Petal.Width   0.246      1.326     2.026
mean(iris[iris$Species == "setosa", "Petal.Length"])
[1] 1.462
  1. write.table或write.csv后打开保存的table, 发现columns都向前移位了,把第一个本来因该空着的格子占了。检查sep没有问题。
    write.table(...,col.names=NA)

  2. 用write.table或write.csv导入数据,但是部分数据有leading 0, 即存在“00001”, “00002”这样形式的ID,而且还是数值型的,这使导入的ID变成了“1”,“2”.
    read.csv(...colClasses = c(rep("character",3)))
    把你导入的file中全部3个columns都转化为字符串格式

  3. 你想按照一个df_name给df的columns重新命名。df_name记录了两列,一列为df的columns names, 一列为要需要替换成的列(df_name$names)。

id <- match(colnames(df), df_name$names)
colnames(df) <- df_name$names[id]
  1. ifelse() 太好用
    e.g. colnames(df) <- ifelse(is.na(id), colnames(df), otherdf$test[id])
    如果id是NA,那df的colnames不变。如果不是NA,那么按照id, 把df的colnames指定为otherdf中test列的对应值
上一篇下一篇

猜你喜欢

热点阅读