在包含差异表达蛋白质结果的dfs中,我想标记哪些蛋白质超过某些显著性阈值(例如logFC>1和p<0.05为up_0.05或p<0.01为up_0.01)。 使用 ifelse,我可以为每个 df 单独执行此操作,但是拥有一个函数会更干净,因为我有很多 df 可以通过这种方式处理。
已经提出了一个类似的问题(dplyr - mutate:使用动态变量名称),但我无法将其转化为解决我的问题,因此如果您能更正我的函数代码以使其工作,我将不胜感激(提供示例数据)
多谢!
示例数据
p.vals <- seq(from=0, to=1, by=.0001)
logFCs <- seq(from=0, to=4, by=.1)
diffEx_proteins <- data.frame(protein=LETTERS[1:1000],
adj.P.Val=sample(p.vals, size=1000, replace=TRUE),
logFC=sample(logFCs, size=1000, replace=TRUE))
功能
mark_significants <- function(comparison){
comparison$paste0(comparison, "up_0.05") <- ifelse(comparison$adj.P.Val <= 0.05 & comparison$logFC >= 1, TRUE, FALSE)
comparison$paste0(comparison, "down_0.05") <- ifelse(comparison$adj.P.Val <= 0.05 & comparison$logFC <= -1, TRUE, FALSE)
comparison$paste0(comparison, "up_0.01") <- ifelse(comparison$adj.P.Val <= 0.01 & comparison$logFC >= 1, TRUE, FALSE)
comparison$paste0(comparison, "down_0.01") <- ifelse(comparison$adj.P.Val <= 0.01 & comparison$logFC <= -1, TRUE, FALSE)
}
用法
mark_significants(diffEx_proteins)
我收到错误"mark_significants(diffEx_proteins) 中的错误: 复杂赋值中的函数无效">
我想得到带有 4 个添加逻辑列的 df,表明蛋白质是否达到定义的阈值水平。
我将在下面解释语法的几个问题。这是固定函数:
mark_significants <- function(comparison){
comparison[,"up_0.05"] <- comparison$adj.P.Val <= 0.05 & comparison$logFC >= 1
comparison[,"down_0.05"] <- comparison$adj.P.Val <= 0.05 & comparison$logFC <= -1
comparison[,"up_0.01"] <- comparison$adj.P.Val <= 0.01 & comparison$logFC >= 1
comparison[,"down_0.01"] <- comparison$adj.P.Val <= 0.01 & comparison$logFC <= -1
return(comparison)
}
test <- mark_significants(diffEx_proteins)
head(test, 3)
# protein adj.P.Val logFC up_0.05 down_0.05 up_0.01 down_0.01
#1 A 0.9612 1.4 FALSE FALSE FALSE FALSE
#2 B 0.8271 3.1 FALSE FALSE FALSE FALSE
#3 C 0.1829 2.5 FALSE FALSE FALSE FALSE
comparison
是一个data.frame
,因此函数paste0
不知道要粘贴什么。本质上,它整理字符串。我假设您想添加一列,在我的编辑中,我使用带有新名称的方括号。与调用comparison$up_0.05
不同,调用 在这里也可以工作,从方括号内添加新列可以动态命名列 - 例如通过paste0
函数。- 如果结果
TRUE/FALSE
,则不需要ifelse
函数,并且比较可以直接从整个列中矢量化。 - 最后,除非指定,否则在函数内修改的变量不会在其外部更改。因此,我们必须告诉
R
通过return
输出函数的结果。要直接修改原始数据,可以使用diffEx_proteins <- mark_significants(diffEx_proteins)
.
编辑
根据评论中的其他信息,此帖子和此帖子提供了解决方案。简而言之,在数据进入函数之前必须提取data.frame
的名称,否则deparse(substitute())
返回整个data.frame
。在这里,该函数将接受data.frame
的名称作为字符向量,get
名称中的数据,并将名称paste
到结果的列名。
mark_significants <- function(comparison){
dat <- get(comparison)
dat[,paste(comparison,"up_0.05", sep = "_")] <- dat$adj.P.Val <= 0.05 & dat$logFC >= 1
dat[,paste(comparison,"down_0.05", sep = "_")] <- dat$adj.P.Val <= 0.05 & dat$logFC <= -1
dat[,paste(comparison,"up_0.01", sep = "_")] <- dat$adj.P.Val <= 0.01 & dat$logFC >= 1
dat[,paste(comparison,"down_0.01", sep = "_")] <- dat$adj.P.Val <= 0.01 & dat$logFC <= -1
return(dat)
}
test1 <- mark_significants(deparse(substitute(diffEx_proteins)))
test2 <- mark_significants("diffEx_proteins")
identical(test1, test2)
# [1] TRUE
非常感谢nya,这使我走上了解决方案的正确轨道! 只有我想将"比较"的名称添加到新列中,因为我稍后会将 colname 用于 VENN 图。
这是我对您的函数的修改版本,其中包括对 colname 的"比较"(您关于比较是数据帧的提示有助于解决其正确用法)
mark_significants_2 <- function(comparison){
comparison[,paste0("comparison","_up_0.05")] <- comparison$adj.P.Val <= 0.05 & comparison$logFC >= 1
comparison[,paste0("comparison","_down_0.05")] <- comparison$adj.P.Val <= 0.05 & comparison$logFC <= -1
comparison[,paste0("comparison","_up_0.01")] <- comparison$adj.P.Val <= 0.01 & comparison$logFC >= 1
comparison[,paste0("comparison","_down_0.01")] <- comparison$adj.P.Val <= 0.01 & comparison$logFC <= -1
return(comparison)
}
慢慢地进入编写函数,您的提示非常适合理解语法问题!
工作但不优雅的解决方案,将数据帧及其名称分开:
mark_significants_3 <- function(comparison, name){
comparison[,paste0(name, "_up_0.05")] <- comparison$adj.P.Val <= 0.05 &
comparison$logFC >= 1
comparison[,paste0(name, "_down_0.05")] <- comparison$adj.P.Val <= 0.05 & c
comparison$logFC <= -1
comparison[,paste0(name, "_up_0.001")] <- comparison$adj.P.Val <= 0.001 &
comparison$logFC >= 1
comparison[,paste0(name, "_down_0.001")] <- comparison$adj.P.Val <= 0.001 &
comparison$logFC <= -1
return(comparison)
}
test3 <- mark_significants_3(diffEx_proteins, "diffEx_proteins")