R 使用笔记:日常备忘

笔记内容:

  • 使用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))
R 使用笔记:日常备忘_第1张图片

如上图所示,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')
R 使用笔记:日常备忘_第2张图片

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

col_rainbow <- rainbow(80, s=0.8, v=1)
# 80代表要生成的颜色数量,参数s和v用于设置颜色的饱和度
R 使用笔记:日常备忘_第3张图片

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, 一样的道理
R 使用笔记:日常备忘_第4张图片
R 使用笔记:日常备忘_第5张图片
  1. 你有两个data.frame,df1的列是df2的行,但是排列顺序不一样。你想用把df2 reorder成df1列的顺序。
    可是说是很拗口了,如下图所示举个例子:
R 使用笔记:日常备忘_第6张图片

如果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
R 使用笔记:日常备忘_第7张图片
  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列的对应值

  2. 在R studio中换一种R version
    在win中:在打开Rstudio的时候按住Ctrl键,会出现让你选择使用哪个R version的界面,选择即可。
    参考:https://support.rstudio.com/hc/en-us/articles/200486138-Changing-R-versions-for-RStudio-desktop

  3. dplyr的group_bysummarise
    group_by并没有改变数据本身,只是提示按照什么分了多少组,如下所示:

> group_by(ToothGrowth,supp, dose)
# A tibble: 60 x 3
# Groups:   supp, dose [6]
     len supp  dose 
     
 1   4.2 VC    0.5  
 2  11.5 VC    0.5  
 3   7.3 VC    0.5  
 4   5.8 VC    0.5  

summarise_all()按照group_by的分组来做数据描述,比方说'mean','sd'等
另外summarise_all()是对传入的dataframe所有的columns(除了用于group_by的columns)做summarise,如果有的columns中不是数值型数据,则会报错,不会跳过。

library(dplyr)
data(ToothGrowth)
summarise_all(group_by(ToothGrowth,supp,dose),'mean')
> summarise_all(group_by(ToothGrowth,supp,dose),'mean')
# A tibble: 6 x 3
# Groups:   supp [?]
  supp  dose    len
    
1 OJ    0.5   13.2 
2 OJ    1     22.7 
3 OJ    2     26.1 
4 VC    0.5    7.98
5 VC    1     16.8 
6 VC    2     26.1 

只选某一列数据做group_by的summary, 则如下所示:

gb = group_by(ToothGrowth,supp,dose)
summarise(gb, len_mean = mean(len),len_sd = sd(len))
> summarise(gb, len_mean = mean(len),len_sd = sd(len))
# A tibble: 6 x 4
# Groups:   supp [?]
  supp  dose  len_mean len_sd
         
1 OJ    0.5      13.2    4.46
2 OJ    1        22.7    3.91
3 OJ    2        26.1    2.66
4 VC    0.5       7.98   2.75
5 VC    1        16.8    2.52
6 VC    2        26.1    4.80
  1. merge
    Outer join: merge(x = df1, y = df2, by = "CustomerId", all = TRUE)
    Left outer: merge(x = df1, y = df2, by = "CustomerId", all.x = TRUE)
    Right outer: merge(x = df1, y = df2, by = "CustomerId", all.y = TRUE)
    Cross join: merge(x = df1, y = df2, by = NULL)
    如果是根据rownames来merge, 则by = 0
    另外参考dplyr的方法:http://stat545.com/bit001_dplyr-cheatsheet.html
  2. 按colname删掉column
    df = df[,-which(names(df) == 'colname')]
  3. as.character()paste(collaps = )
> as.character(c(1,2,3))
[1] "1" "2" "3"
> paste(c('1','2','3'), collapse = '_')
[1] "1_2_3"
  1. strsplit() 用来split string
> strsplit("tax_report_A1_22",'_')
[[1]]
[1] "tax"    "report" "A1"     "22" 
  1. veganadonis()做permanova出现负值R2
    注意这里虽然没有报错,但是有个warning():
    Warning message: In vegdist(lhs, method = method, ...) : results may be meaningless because data have negative entries in method “bray”
    大概是因为permanova的input需要距离矩阵,默认是使用BC距离。但是有些数据可能并不适合使用BC距离。换成adonis( method = "euclidean")就没有负值R2存在了。
    这是一个报错的源码,虽然没看明白怎么肥四,但是anyway问题得到了解决。
    ┑( ̄Д  ̄)┍
> adonis(formula = qd_shap ~ BMI, data=qd_meta, permutations = 99)

Call:
adonis(formula = qd_shap ~ BMI, data = qd_meta, permutations = 99)

Permutation: free
Number of permutations: 99

Terms added sequentially (first to last)

          Df SumsOfSqs   MeanSqs F.Model       R2 Pr(>F)
BMI         1 -35009042 -35009042 -74.954 -0.15646   0.81
Residuals 554 258759663    467075          1.15646
Total     555 223750621                    1.00000
Warning message:
In vegdist(lhs, method = method, ...) :
 results may be meaningless because data have negative entries in method “bray”



> adonis(formula = qd_shap ~ BMI, data=qd_meta, permutations = 99, method = 'euclidean')

Call:
adonis(formula = qd_shap ~ BMI, data = qd_meta, permutations = 99, method = "euclidean")

Permutation: free
Number of permutations: 99

Terms added sequentially (first to last)

          Df SumsOfSqs MeanSqs F.Model      R2 Pr(>F)
BMI         1      2.04  2.0430  1.4336 0.00258   0.17
Residuals 554    789.50  1.4251         0.99742
Total     555    791.54                 1.00000
  1. get()
    在formula,循环等中需要用到变量,但是不能直接传递变量,可以使用get(变量名称)传递。
data(ToothGrowth)
adonis(len ~ supp, data = ToothGrowth)  

a = 'supp'
adonis(len ~ get(a), data = ToothGrowth) # 与上结果一样
  1. grep()
data(ToothGrowth)
ToothGrowth[grep('^V',ToothGrowth$supp),]
# 把ToothGrowth$supp中以V开头的行捞出来
  1. 在string中替换字符
    一般来说:
gsub('plant',"animal","a room filled with plants")
[1] "a room filled with animals"

对于dataframe整列的操作,最好用stringi包:
stri_replace_all(df[,'colname'], 'new_string', fixed='old string')

> head(ToothGrowth)
   len supp dose
1  4.2   VC  0.5
2 11.5   VC  0.5
3  7.3   VC  0.5
4  5.8   VC  0.5
5  6.4   VC  0.5
6 10.0   VC  0.5
> ToothGrowth$new = stri_replace_all(ToothGrowth[,'supp'],'.cc',fixed = 'C')
> head(ToothGrowth)
   len supp dose  new
1  4.2   VC  0.5 V.cc
2 11.5   VC  0.5 V.cc
3  7.3   VC  0.5 V.cc
4  5.8   VC  0.5 V.cc
5  6.4   VC  0.5 V.cc
6 10.0   VC  0.5 V.cc
  1. merge list of dataframes
    reshape包的merge_all()
    merge_all(list_of_dfs,...)

  2. 韦恩图

library(gplots)
test = venn(list(g1=c('a','b','c','d'),
                 g2=c('a','b','c','e','f','h'),
                 g3=c('a','b','c','o','r','h')))

> test
    num g1 g2 g3
000   0  0  0  0
001   2  0  0  1
010   2  0  1  0
011   1  0  1  1
100   1  1  0  0
101   0  1  0  1
110   0  1  1  0
111   3  1  1  1
attr(,"intersections")
attr(,"intersections")$g1
[1] "d"

attr(,"intersections")$g2
[1] "e" "f"

attr(,"intersections")$g3
[1] "o" "r"

attr(,"intersections")$`g2:g3`
[1] "h"

attr(,"intersections")$`g1:g2:g3`
[1] "a" "b" "c"

attr(,"class")
[1] "venn"
R 使用笔记:日常备忘_第8张图片
  1. 筛选df中列非零个数>100的列:
    df[,colSums(df!=0) > 100]

  2. RStudio: 在Global环境里删掉某个特定变量

R 使用笔记:日常备忘_第9张图片
R 使用笔记:日常备忘_第10张图片

选中,然后点小扫帚删掉。

  1. 一个已经导入的dataframe, 要把第一行设置为header
    colnames(df) <- as.character(unlist(df[1,]))
    df = df[-1, ]

  2. 在ATOM中运行R,出现:no kernel for grammar R found
    需要安装一个juypter R kernel, 在R studio或者R base里运行:
    install.packages('IRkernel')
    IRkernel::installspec()
    见 https://github.com/IRkernel/IRkernel

  3. 关掉科学计数法(scientific natation)
    options(scipen = 999)
    再打开:
    options(scipen = 0)
    或者:
    format(xxx,scientific=F)

  4. 按照df2的col2来sort df1的col1
    df1[order(match(df2[,'col2'], df1[,'col1']),]

你可能感兴趣的:(R 使用笔记:日常备忘)