2017-05-29 78 views
2

我有以下tibble筛选每列行:如何使用独立dplyr


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

+0

[过滤基于特定值data.frame中的每一列(HTTPS的可能重复:// stackoverflow.com/questions/28183653/filter-each-column-of-a-data-frame-based-on-a-specific-value) – www

+1

我想你想''= 2'因为2的值出现在所需的输出。 – neilfws

+0

@neilfws:你是对的。我更新了。 – pdubois

回答

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 
5

即将dplyr 0.6(现在从GitHub安装,如果你喜欢)具有filter_at,其可被用于过滤到具有大于或等于2的值的任何行,然后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 

或者类似地,

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

可以翻译为与dplyr 0.5一起使用:

df %>% 
    mutate_at(vars(-gene), funs(na_if(., . < 2))) %>% 
    filter(rowSums(is.na(.)) < (ncol(.) - 1)) 

所有返回相同的东西。

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