8 推荐一个 R 中很好用的条件判断语句

text <- "Gene   log2FoldChange  padj
a   1   0.1
b   2   0.05
d   3   0.001
e   -2  0.0002
G   0   0.0001"

res_output <- read.table(text=text, row.names=NULL, header=T)

padj_thresh = 0.05
log2FC = 1
groupA = 'trt'
groupB = 'untrt'

8.1 ifelse 标记差异基因

不想安装额外的包,可以用 ifelse,要稍微复杂一点。

res_output$level <- ifelse(res_output$padj<=padj_thresh,
                      ifelse(res_output$log2FoldChange>=log2FC,
                             paste(groupA,"UP"),
                             ifelse(res_output$log2FoldChange<=(-1)*(log2FC),
                                    paste(groupB,"UP"), "NoDiff")) , "NoDiff")

res_output$level <- 
ifelse(res_output$padj<=padj_thresh & res_output$log2FoldChange>=log2FC, paste(groupA,"UP"),
ifelse(res_output$padj<=padj_thresh & res_output$log2FoldChange<=(-1)*(log2FC), paste(groupB,"UP"),
       "NoDiff")) 

8.2 dplyr::case-when 标记差异基因

比之前简洁了一些,可读性强

library(dplyr)

res_output %>% dplyr::mutate(level = case_when(
  (padj<=padj_thresh) & (log2FoldChange>=log2FC) ~ paste(groupA,"UP"),
  (padj<=padj_thresh) & (log2FoldChange<=(-1)*log2FC) ~ paste(groupB, "UP"),
  TRUE ~ "NoDiff"
  ))
##   Gene log2FoldChange  padj    level
## 1    a              1 1e-01   NoDiff
## 2    b              2 5e-02   trt UP
## 3    d              3 1e-03   trt UP
## 4    e             -2 2e-04 untrt UP
## 5    G              0 1e-04   NoDiff

8.3 dplyr::if_else 会更快一点

速度快一点,但可读性弱了一些。

res_output %>% dplyr::mutate(level = 
if_else(res_output$padj<=padj_thresh & res_output$log2FoldChange>=log2FC, paste(groupA,"UP"),
if_else(res_output$padj<=padj_thresh & res_output$log2FoldChange<=(-1)*(log2FC), paste(groupB,"UP"),
       "NoDiff"))) 
##   Gene log2FoldChange  padj    level
## 1    a              1 1e-01   NoDiff
## 2    b              2 5e-02   trt UP
## 3    d              3 1e-03   trt UP
## 4    e             -2 2e-04 untrt UP
## 5    G              0 1e-04   NoDiff

8.4 case-when只保留差异基因的名字

library(dplyr)
res_output %>% dplyr::mutate(diff_gene = case_when(
  (padj<=padj_thresh) & (log2FoldChange>=log2FC) ~ Gene,
  (padj<=padj_thresh) & (log2FoldChange<=(-1)*log2FC) ~ Gene,
  TRUE ~ ""
  ))
##   Gene log2FoldChange  padj    level diff_gene
## 1    a              1 1e-01   NoDiff          
## 2    b              2 5e-02   trt UP         b
## 3    d              3 1e-03   trt UP         d
## 4    e             -2 2e-04 untrt UP         e
## 5    G              0 1e-04   NoDiff

8.5 case-when每隔 1 个基因保留 1 个

临时生成列时操作起来更方便了

library(dplyr)
res_output %>% dplyr::mutate(rank=1:n(),
                       keep_gene = case_when(
  rank %% 2 == 1 ~ Gene,
  TRUE ~ ""
  ))
##   Gene log2FoldChange  padj    level rank keep_gene
## 1    a              1 1e-01   NoDiff    1         a
## 2    b              2 5e-02   trt UP    2          
## 3    d              3 1e-03   trt UP    3         d
## 4    e             -2 2e-04 untrt UP    4          
## 5    G              0 1e-04   NoDiff    5         G

8.6 dplyr::if_else速度最快!

dplyr::if_else速度最快!

suppressPackageStartupMessages(library(tidyverse))

microbenchmark::microbenchmark(
  case_when(1:1000 < 100 ~ "low", TRUE ~ "high"),
  if_else(1:1000 < 3, "low", "high"),
  ifelse(1:1000 < 3, "low", "high")
)
#> Unit: microseconds
#>                                            expr     min      lq     mean
#>  case_when(1:1000 < 100 ~ "low", TRUE ~ "high") 384.786 418.629 953.4921
#>              if_else(1:1000 < 3, "low", "high")  61.943  67.686 128.9811
#>               ifelse(1:1000 < 3, "low", "high") 256.797 264.796 391.7180
#>    median       uq       max neval
#>  631.9420 708.4480 33149.364   100
#>   90.0435 127.9885  2496.182   100
#>  327.9695 460.8810  2354.246   100

Ref: https://community.rstudio.com/t/case-when-why-not/2685/2

如果不想安装额外包,用ifelse;如果是单个条件,用dplyr::if_else;如果多个条件,用dplyr::case_when (更可读)。