我有以下数据框:
dat <- structure(list(`A-XXX` = c(1.51653275922944, 0.077037240321129,
0), `fBM-XXX` = c(2.22875185527511, 0, 0), `P-XXX` = c(1.73356698481106,
0, 0), `vBM-XXX` = c(3.00397859609183, 0, 0)), .Names = c("A-XXX",
"fBM-XXX", "P-XXX", "vBM-XXX"), row.names = c("BATF::JUN_AHR",
"BATF::JUN_CCR9", "BATF::JUN_IL10"), class = "data.frame")
dat
#> A-XXX fBM-XXX P-XXX vBM-XXX
#> BATF::JUN_AHR 1.51653276 2.228752 1.733567 3.003979
#> BATF::JUN_CCR9 0.07703724 0.000000 0.000000 0.000000
#> BATF::JUN_IL10 0.00000000 0.000000 0.000000 0.000000
我可以使用以下命令删除所有列为零的行:
> dat <- dat[ rowSums(dat)!=0, ]
> dat
A-XXX fBM-XXX P-XXX vBM-XXX
BATF::JUN_AHR 1.51653276 2.228752 1.733567 3.003979
BATF::JUN_CCR9 0.07703724 0.000000 0.000000 0.000000
但是我怎么能用dplyr的管道风格呢?
答案 0 :(得分:5)
这是一个dplyr选项:
library(dplyr)
filter_all(dat, any_vars(. != 0))
# A-XXX fBM-XXX P-XXX vBM-XXX
#1 1.51653276 2.228752 1.733567 3.003979
#2 0.07703724 0.000000 0.000000 0.000000
这里我们使用逻辑,如果任何变量不等于零,我们将保留它。它与删除所有变量等于零的行相同。
关于row.names:
library(tidyverse)
dat %>% rownames_to_column() %>% filter_at(vars(-rowname), any_vars(. != 0))
# rowname A-XXX fBM-XXX P-XXX vBM-XXX
#1 BATF::JUN_AHR 1.51653276 2.228752 1.733567 3.003979
#2 BATF::JUN_CCR9 0.07703724 0.000000 0.000000 0.000000
答案 1 :(得分:2)
我们可以使用reduce
中的purrr
来获取行的总和,并根据逻辑向量获取数据集filter
library(tidyverse)
dat %>%
reduce(`+`) %>%
{. != 0} %>%
filter(dat, .)
# A-XXX fBM-XXX P-XXX vBM-XXX
#1 1.51653276 2.228752 1.733567 3.003979
#2 0.07703724 0.000000 0.000000 0.000000
注意:在%>%
内,row.names被剥离。最好创建一个新列或稍后分配row.names
如果我们还需要行名,那么请尽早创建行名列,然后使用它来更改行末的名称
dat %>%
rownames_to_column('rn') %>%
filter(rowSums(.[-1]) != 0) %>%
`row.names<-`(., .[['rn']]) %>% select(-rn)
# A-XXX fBM-XXX P-XXX vBM-XXX
#BATF::JUN_AHR 1.51653276 2.228752 1.733567 3.003979
#BATF::JUN_CCR9 0.07703724 0.000000 0.000000 0.000000
答案 2 :(得分:2)
添加到@mgrund 的答案中, dplyr 1.0.0 更短的替代方案是:
# Option A:
data %>% filter(across(everything(.)) != 0))
# Option B:
data %>% filter(across(everything(.), ~. == 0))
说明:
across()
检查每个 tidy_select 变量,其中 everything()
代表每一列。在选项 A 中,如果不是零,则检查每一列,这在每一列中加起来是一整行零。在选项 B 中,在每一列上,应用公式 (~) 来检查当前列是否为零。
编辑:
由于 filter
已经按行检查,因此您不需要 rowwise()
。 select
或 mutate
的情况有所不同。
重要提示:
在选项A中,写across(everything(.)) != 0
,
很重要
并不是
across(everything(.) != 0))
!
原因:
across
需要一个 tidyselect 变量(此处为 everything()
),而不是布尔值(即 everything(.) != 0)
)
答案 3 :(得分:2)
您可以使用新的 if_any()
。我在 if_any()
library(dplyr)
library(tibble)
dat <- structure(list(`A-XXX` = c(1.51653275922944, 0.077037240321129,
0), `fBM-XXX` = c(2.22875185527511, 0, 0), `P-XXX` = c(1.73356698481106,
0, 0), `vBM-XXX` = c(3.00397859609183, 0, 0)), .Names = c("A-XXX",
"fBM-XXX", "P-XXX", "vBM-XXX"), row.names = c("BATF::JUN_AHR",
"BATF::JUN_CCR9", "BATF::JUN_IL10"), class = "data.frame")
dat
#> A-XXX fBM-XXX P-XXX vBM-XXX
#> BATF::JUN_AHR 1.51653276 2.228752 1.733567 3.003979
#> BATF::JUN_CCR9 0.07703724 0.000000 0.000000 0.000000
#> BATF::JUN_IL10 0.00000000 0.000000 0.000000 0.000000
dat %>%
rownames_to_column("ID") %>%
filter(if_any(!matches("ID"), ~ . != 0)) %>%
column_to_rownames("ID")
#> A-XXX fBM-XXX P-XXX vBM-XXX
#> BATF::JUN_AHR 1.51653276 2.228752 1.733567 3.003979
#> BATF::JUN_CCR9 0.07703724 0.000000 0.000000 0.000000
由 reprex package (v1.0.0) 于 2021 年 4 月 12 日创建
答案 4 :(得分:1)
这是第三个选项,它使用purrr::pmap
生成所有行是否为零的索引。绝对不如filter_at
那么紧凑,但使用pmap
打开了有趣和复杂条件的选项!
dat <- structure(list(`A-XXX` = c(1.51653275922944, 0.077037240321129,
0), `fBM-XXX` = c(2.22875185527511, 0, 0), `P-XXX` = c(1.73356698481106,
0, 0), `vBM-XXX` = c(3.00397859609183, 0, 0)), .Names = c("A-XXX",
"fBM-XXX", "P-XXX", "vBM-XXX"), row.names = c("BATF::JUN_AHR",
"BATF::JUN_CCR9", "BATF::JUN_IL10"), class = "data.frame")
library(tidyverse)
dat %>%
rownames_to_column() %>%
bind_cols(all_zero = pmap_lgl(., function(rowname, ...) all(list(...) == 0))) %>%
filter(all_zero == FALSE) %>%
`rownames<-`(.$rowname) %>%
select(-rowname, -all_zero)
#> A-XXX fBM-XXX P-XXX vBM-XXX
#> BATF::JUN_AHR 1.51653276 2.228752 1.733567 3.003979
#> BATF::JUN_CCR9 0.07703724 0.000000 0.000000 0.000000
由reprex package(v0.2.0)创建于2018-03-14。
答案 5 :(得分:1)
这里是使用dplyr的逐行运算的另一种选择(col1,col2,col3
定义了三个示例列,针对这些列计算了行总和)
library(tidyverse)
df <- df %>%
rowwise() %>%
filter(sum(c(col1,col2,col3)) != 0)
或者,如果您有大量的变量(列)可供选择,则还可以通过以下方式使用tidyverse选择语法:
df <- df %>%
rowwise() %>%
filter(sum(c_across(col1:col3)) != 0)
有关详细信息,请参见:https://dplyr.tidyverse.org/articles/rowwise.html