如何使用 dplyr 独立过滤每一列的行
How to filter rows for every column independently using 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列。
一个解决方案:从宽格式转换为长格式,这样您就可以只过滤一列,然后在最后根据需要转换回宽格式。请注意,这将丢弃没有值满足条件的基因。
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
即将推出的 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))
全部return一样。
我们可以使用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
我有以下问题:
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列。
一个解决方案:从宽格式转换为长格式,这样您就可以只过滤一列,然后在最后根据需要转换回宽格式。请注意,这将丢弃没有值满足条件的基因。
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
即将推出的 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))
全部return一样。
我们可以使用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