R dpylr select_if有多个条件

时间:2016-09-20 11:28:19

标签: r select dplyr

我想按名称选择所有数字变量以及一些变量。我已设法使用select_if来获取数值变量并选择按名称获取这些变量,但不能将这两者合并为一个语句

x = data.table(c(1,2,3),c(10,11,12),c('a','b','c'),c('x','y','z'), c('l', 'm','n'))

我希望我的结果是:

V1 V2 V4 V5
1 10  x l
2 11  y m
3 12  z n

我试过了,但它没有用

y = x %>%
select_if(is.numeric, V4, V5)

3 个答案:

答案 0 :(得分:10)

如果我们有数据框,x

x = data.frame(V1=c(1,2,3),V2=c(10,11,12),V3=c('a','b','c'),V4=c('x','y','z'),V5=c('l', 'm','n'), stringsAsFactors=FALSE)
##  V1 V2 V3 V4 V5
##1  1 10  a  x  l
##2  2 11  b  y  m
##3  3 12  c  z  n

其中V1V2实际上是numeric而其余列不是因素,我们可以这样做:

library(dplyr)
y <- x %>% select_if(function(col) is.numeric(col) | 
                                   all(col == .$V4) | 
                                   all(col == .$V5))
##  V1 V2 V4 V5
##1  1 10  x  l
##2  2 11  y  m
##3  3 12  z  n

不是说这是最好的事情,但它确实做你想做的事。这里的问题是select_if期望它的函数返回一个对应于所有列的布尔向量。

另一种方法是使用select

y <- x %>% select(which(sapply(.,class)=="numeric"),V4,V5)
##  V1 V2 V4 V5
##1  1 10  x  l
##2  2 11  y  m
##3  3 12  z  n

这可能更好。

答案 1 :(得分:4)

map的一个选项(来自purrr

library(purrr)
x %>%
     map2(names(x), ~.[is.numeric(.x)|.y != "V3"])  %>%
     Filter(length, .) %>% 
     bind_cols
 #     V1    V2    V4    V5
 #  <dbl> <dbl> <chr> <chr>
 #1     1    10     x     l
 #2     2    11     y     m
 #3     3    12     z     n

或@RoyalTS建议

x %>% 
    imap( ~ .[is.numeric(.x)|.y != "V3"]) %>%
    keep(~length(.x) > 0) %>%
    bind_cols

由于数据集为data.table,因此data.table的子集选项将为

x[, sapply(x, is.numeric) | colnames(x) != "V3", with = FALSE]
#   V1 V2 V4 V5
#1:  1 10  x  l
#2:  2 11  y  m
#3:  3 12  z  n

数据

x <- data.table(c(1,2,3),c(10,11,12),c('a','b','c'),c('x','y','z'), 
              c('l', 'm','n')) 

注意:@nicola提到了为什么cbind不是必需的。因此,我们没有描述已经提出的相同问题。

答案 2 :(得分:-1)

使用data.frame函数:

x = data.frame(V1=c(1,2,3),V2=c(10,11,12),V3=c('a','b','c'),V4=c('x','y','z'),V5=c('l', 'm','n'))

然后x %>% select_if(is.numeric)有效。