R 使用笔记:日常备忘
笔记内容:
- 使用Rstudio的快捷键及tips
- 一些工作中常用、有用的packages及函数
- 各种日常备忘
- ... ...
-
Rstudio中批量注释
Ctrl + shift + C -
把list转化为vector
一些函数的input会要求数据格式必须为vector,比如需要将data.frame中跳出来一列(list)转化为vector, 且可以将其character分Levels,作为factor呈现。
vector = unlist(list, use.names = FALSE)
- 寻找重复值
duplicated()
在data.frame中寻找重复值, df[duplicated(df['ID']), ]
即返回df中ID列的重复值。duplicated()
本身返回一个Logic变量。
- 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指向相应的点。
详情可以参考这个链接
- 连续型变量的分层(变为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有多少样本落在里面
- package
ggplot2
的强大画图功能
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
-
is.na()
is.na(i)
可以知道i中的缺失值。即为NA(not available)的值。其返回为Ture&False。使用table(is.na(i))
统计i中的缺失值有多少个。
!is.na()
即查看非缺失值 -
read.table()
有时候直接使用read.table()
读取文档,R会在column names上加上X,比方说纯数字的column names3-1, 3-2, 3-3
这样,会变成X3-1, X3-2, X3-3
加上check.names = FALSE
即可 -
subset data.frame
bar <- subset(foo, location == "there")
foo[foo$location == "there", ] #不要忘了逗号,逗号左边subset行,右边subset列
- 把data.frame中的两列string, 合并为一列,并以指定连接符连接:
paste
meta$detail <- paste(meta$sample_position,meta$treatment, sep = '_')
# meta中sample_position与treatment两列以下划线连接起来,成为新列detail
-
在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')
就可以使用了
参考这个链接 -
使用
brewer.pal
,rainbow()
,colorRampPalette
调色作图
RColorBrewer
是很棒的调色板包,它的好处在提供各种服务于各种不同类型的数据(有序离散型,无序离散型,连续型变量等),用颜色的深浅表现循序渐进的关系。色彩饱和度较低不刺眼,又可以显著区分的颜色区分数据中不同的类别。但也存在调色板少,调色板中颜色也太少,不能在超多变量情况下使用的问题。这个问题可以用rainbow()
来解决。
主要有以下三种调色板:
(1)有序变量的调色板(sequential):从高到低,从小到大的数据,用从浅到深的颜色表示。需要注意的是每个调色板可用的颜色数目只有3-9个。也就是说要用不同颜色表示的类别,最少要有3个,最多只能有9个。
(2)两极分化的调色板(divergent):在热图的图例中常见,主要关注的是数据的两极分化情况。关注变量在哪些样本中富集,在哪些样本中稀疏。需要注意的是每个调色板可用的颜色数目只有3-11个。
(3)无序分类的调色板(qualitative):各类之间地位等同,没有顺序之分。需要注意的是每个调色板可用的颜色数目根据不同的Set有着不同的颜色上限,其下限均为3个,上限最高的为12个。
顺便一提Pastel1
和Pastel2
这两个调色盘颜色饱和度很低,可以说是马卡龙色和莫兰迪色了;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相对应起来的一众颜色了
- 按照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, 一样的道理
- 你有两个data.frame,df1的列是df2的行,但是排列顺序不一样。你想用把df2 reorder成df1列的顺序。
可是说是很拗口了,如下图所示举个例子:
如果sample的顺序可以直接正序或者倒序当然很方便,但是如果df是按照固定顺序排列的,你在某个热图中想用这种顺序展示结果。
使用match
来把顺序记录下来:
df2_ <- df2[,match(rownames(df1), colnames(df2))]
##df2行的顺序就变成df1列的顺序了
- 在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
- 分组求均值及标准差: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平均值。
- R的函数不能return超过一个对象:不能
return(a, b)
, 怎么办?
在function中写入:
...
list <- list("name1" = a, "name2" = b)
return (list)
# 在需要使用时用$
output <- fun()
a <- output$name1
b <- output$name2
- linux中更新R-base
$ sudo apt-get install r-base
$ sudo apt upgrade r-base r-base-dev
$ sudo apt update
$ sudo apt upgrade
-
在windows系统中
setwd()
设置路径
C:\Users\Usernames\Desktop\工作\项目A
-------> C:/Users/Usernames/Desktop/工作/项目A -
cbind()
的局限
cbind()
的output是一个matrix,这意味着它只能容忍一种类型的数据。要么全是数值型,要么全是分类型。如果你试图把一列factorcbind()
到另一个dataframe上,可能会出现factor全部变成数值(level个数)的情况。这种时候还是用data.frame()
(多么鸡肋,要你何用?=_=)
data.frame(df1, group = df2$factor)
-
函数中传参数用于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"
-
去除含有NA的行(把所有带NA的都去掉)
data <- data[complete.cases(data), ]
-
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
-
write.table或write.csv后打开保存的table, 发现columns都向前移位了,把第一个本来因该空着的格子占了。检查sep没有问题。
write.table(...,col.names=NA)
-
用write.table或write.csv导入数据,但是部分数据有leading 0, 即存在“00001”, “00002”这样形式的ID,而且还是数值型的,这使导入的ID变成了“1”,“2”.
read.csv(...colClasses = c(rep("character",3)))
把你导入的file中全部3个columns都转化为字符串格式 -
你想按照一个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]
- ifelse() 太好用
e.g.colnames(df) <- ifelse(is.na(id), colnames(df), otherdf$test[id])
如果id是NA,那df的colnames不变。如果不是NA,那么按照id, 把df的colnames指定为otherdf中test列的对应值