如何使用dplyr独立过滤每列的行

时间:2017-05-29 00:45:46

标签: r dplyr tidyverse

我有以下几点:


library(tidyverse)
df <- tibble::tribble(
  ~gene, ~colB, ~colC,
  "a",   1,  2,
  "b",   2,  3,
  "c",   3,  4,
  "d",   1,  1
)

df
#> # A tibble: 4 x 3
#>    gene  colB  colC
#>   <chr> <dbl> <dbl>
#> 1     a     1     2
#> 2     b     2     3
#> 3     c     3     4
#> 4     d     1     1

我想要做的是过滤gene列后的每一列 对于大于或等于2(> = 2)的值。结果如下:

gene, colB, colC
a   NA   2
b   2    3
c   3    4

我怎样才能做到这一点?

基因之后的列数实际上不仅仅是2。

3 个答案:

答案 0 :(得分:5)

即将推出的dplyr 0.6(现在从GitHub安装,如果你愿意的话)有filter_at,它可用于过滤任何值大于或等于2的行,然后{{1} }可以通过na_if类似地应用,所以

mutate_at

或类似地,

df %>% 
    filter_at(vars(-gene), any_vars(. >= 2)) %>% 
    mutate_at(vars(-gene), funs(na_if(., . < 2)))
#> # A tibble: 3 x 3
#>    gene  colB  colC
#>   <chr> <dbl> <dbl>
#> 1     a    NA     2
#> 2     b     2     3
#> 3     c     3     4

可以翻译用于dplyr 0.5:

df %>% 
    mutate_at(vars(-gene), funs(na_if(., . < 2))) %>% 
    filter_at(vars(-gene), any_vars(!is.na(.)))

所有回报都是一样的。

答案 1 :(得分:4)

一种解决方案:从宽格式转换为长格式,因此您可以只对一列进行过滤,然后根据需要在最后转换回宽度。请注意,这将丢弃没有值满足条件的基因。

library(tidyverse)
df %>% 
gather(name, value, -gene) %>% 
  filter(value >= 2) %>% 
  spread(name, value)

# A tibble: 3 x 3
   gene  colB  colC
* <chr> <dbl> <dbl>
1     a    NA     2
2     b     2     3
3     c     3     4

答案 2 :(得分:0)

我们可以使用data.table

library(data.table)
setDT(df)[df[, Reduce(`|`, lapply(.SD, `>=`, 2)), .SDcols = colB:colC]
   ][, (2:3) := lapply(.SD, function(x) replace(x, x < 2, NA)), .SDcols = colB:colC][]
#   gene colB colC
#1:    a   NA    2
#2:    b    2    3
#3:    c    3    4

melt/dcast

dcast(melt(setDT(df), id.var = 'gene')[value>=2], gene ~variable)
#   gene colB colC
#1:    a   NA    2
#2:    b    2    3
#3:    c    3    4