因为在工作中常常会遇到,需要根据样本名称,新建分组情况划分treat或者control组,有多种代码方式,在这里总结记录一下,以备不时之需求。
比如这样的数据,必然要根据title划分control或者treat组
期待效果应该是这样的
先建立数据框,方便练习,给出代码
group <- data.frame(
ID=c("GSM1052615",
"GSM1052616",
"GSM1052617",
"GSM1052618",
"GSM1052619",
"GSM1052620"),
title=c("A375 cells 24h Control rep1",
"A375 cells 24h Control rep2",
"A375 cells 24h Control rep3",
"A375 cells 24h Vemurafenib rep1",
"A375 cells 24h Vemurafenib rep2",
"A375 cells 24h Vemurafenib rep3"))
x <- ifelse(str_detect(group$title,"Control"),"control","treat")
group$group <- x
法1利用的是基础包的ifelse函数,和stringr包的str_detect函数。两根函数的格式也很清晰如下图:
ifelse第一个参数返回逻辑值,T or F,如果返回的是TRUE就执行第二项参数,如果返回的是FALSE就执行第三项参数.那么很自然而然就想要找能返回逻辑值的东西填在第一个参数那里。关于逻辑值的问题,像%in%,str_detect都是返回逻辑值的,而像which和match函数是返回下标位置的,虽然二者在配合[ ]符号进行取值时可以达到相同的效果,但在ifelse时我们显然需要选择返回逻辑值的函数。这里用str_detect,他的作用是对字符串进行操作,查找有无特定的字符,第一个参数输入被查找的字符串向量,第二个参数标注要求查找字符串,有的就会返回T,没有的返回F。这样搭配ifelese,就会得到下图的结果 。
把结果储存给x,再新建一列赋值就好啦。
a <- mutate(group[str_detect(group$title,"Control"),],group=rep("control",3))
b <- mutate(group[!str_detect(group$title,"Control"),],group=rep("treat",3))
x <- rbind(a,b)
稍微绕了一点,核心依然是str_detect函数。前文讲到,返回的逻辑值可以和[ ]搭配取值,这里的核心思想时将group数据框中有control和没有control(用!来取相反逻辑值)的数据分别取出来,再利用tidyverse包的mutate函数快捷给数据添加分组信息。mutate函数给数据框添加新列很好用,第一个参数指定数据,第二个参数 新列名=数据就可以了。效果如图,最后把两个数据一合并就行。合并的时候注意a b的列名是一致的,所以按照“按行合并(rbind)(row),列名一致”的原则,用rbind函数。
group[str_detect(group$title,"Control"),'group'] <- "control"
group[!str_detect(group$title,"Control"),'group'] <- "treat"
代码用的函数最少,但是逻辑有点难记,需要多加练习。
str_detect用来取出逻辑值。[ ]中,逗号前面的部分用来取出相关的行,即前三行/后三行,逗号后面的"group"是需要新建列的名称,<- 后面的则是给新列赋值
灵感来源于常见的一段代码:
data[which(data$age < 18),'age_group'] <- "young"
data是一个有age变量的数据,希望把年龄小于18的定义为"young"
只不过这里用来取数据的不是逻辑值,而是which和他定义的下标
这个其实不是个方法 只是纪念一下自己刚刚开始学R写出来的代码,大抵就是从这会儿开始觉得要掌握R基础
一顿操作猛如虎
myseries$Condition <- c(rep(NA,length(myseries$Series)))
for (i in(1:length(myseries$Series))) {
myseries$Condition[i] <- unlist(strsplit(myseries$Sample[i], "_"))[length(unlist(strsplit(myseries$Sample[i], "_")))-1]
}
草草看了一下,大概是用strsplit来把sample打散(甚至用的不是str_split),然后用unlist取消list格式(甚至不会simplify=T),然后for循环赋值进去,也没想到可以直接写赋值,还提取了原文的赋值
数据如图所示:
要求:
# a< -1 且b<0.05,则x对应的值为down;
# a>1 且b<0.05,则x对应的值为up;
# 其他情况,x对应的值为no
结果:
传统的取下标难以应对“其他情况,x对应的值为no”,这里做了一个函数来填补NA值
deg[which(deg$a<(-1) & deg$b<0.05),"x"] <- "down"
deg[which(deg$a>1 & deg$b<0.05),"x"] <- "up"
FillNA <- function(x){#填充NA
x[is.na(x )]<- "no";
x
}
deg$x <- FillNA(deg$x)
table(deg$x)
# down no up
# 1059 28863 853
利用ifelse进行嵌套
# 定义两个变量
k1 <- deg$a<(-1) & deg$b<0.05
k2 <- deg$a>1 & deg$b<0.05
deg$x <- ifelse(k1,"down",ifelse(k2,"up","no"))
table(deg$x)
# down no up
# 1059 28863 853
ifelse的嵌套是非常好的分类工具,单独使用或者配合str_detect返回的逻辑值都很好用