dplyr:取消选择的列

时间:2017-10-19 10:54:38

标签: r dplyr tidyverse

如何取消选择自编函数的...参数中给出的列。 (我还需要在其他位置选择列,因此仅在-中指定...列并不能解决我的问题。)

任何解决方案都是apreciated,select - 助手,操纵quosures或表达式,......

# very simple example data
test <- data.frame(a=1:3, b=1:3, c=1:3)

# function skeleton
testfun <- function(x, ...){
  y <- select(x, ...)
  z <- select(x, -...) # does of course not work like this
  return(list(y, z))   # just as an example
}

# calling the function to select different columns
testfun(test, a)
testfun(test, a, b)

4 个答案:

答案 0 :(得分:6)

这些最简单的解决方案是选择正列,然后比较名称以确定要删除的列,如this answer中所示。

直接处理点,

  1. 我们会在一系列状态(quos)中捕获它们。
  2. 使用UQS取消引用并拼接点以进行正选择。
  3. c()内做同样的事情,以便我们有一个选择向量。
  4. 否定该矢量进行否定选择。
  5. 这是(3)和(4)描述的转换。

    library(dplyr)
    dots <- quos(a, b)
    quos(-c(UQS(dots)))
    #> [[1]]
    #> <quosure: frame>
    #> ~-c(~a, ~b)
    #> 
    #> attr(,"class")
    #> [1] "quosures"
    

    那么完整的解决方案就是

    test <- data.frame(a = 1:3, b = 1:3, c = 1:3)
    
    # function skeleton
    testfun <- function(x, ...) {
      dots <- quos(...)
      y <- select(x, UQS(dots))
      z <- select(x, -c(UQS(dots)))
      return(list(y, z))   
    }
    
    testfun(test, a)
    #> [[1]]
    #>   a
    #> 1 1
    #> 2 2
    #> 3 3
    #> 
    #> [[2]]
    #>   b c
    #> 1 1 1
    #> 2 2 2
    #> 3 3 3
    
    testfun(test, a, b)
    #> [[1]]
    #>   a b
    #> 1 1 1
    #> 2 2 2
    #> 3 3 3
    #> 
    #> [[2]]
    #>   c
    #> 1 1
    #> 2 2
    #> 3 3
    

    测试选择助手。

    testfun(test, starts_with("b"), one_of("c"))
    #> [[1]]
    #>   b c
    #> 1 1 1
    #> 2 2 2
    #> 3 3 3
    #> 
    #> [[2]]
    #>   a
    #> 1 1
    #> 2 2
    #> 3 3
    

答案 1 :(得分:2)

您可以将此技巧与purrr::modify_at

一起使用
library(purrr)
testfun <- function(x, ...){
  y <- select(x, ...)
  z <- modify_at(x,c(...),~NULL)
  return(list(y, z))   # just as an example
}

testfun(test,"a")
# [[1]]
#   a
# 1 1
# 2 2
# 3 3
# 
# [[2]]
#   b c
# 1 1 1
# 2 2 2
# 3 3 3

答案 2 :(得分:1)

那个怎么样?

testfun <- function(x, ...){
  y <- select(x, ...)
  z <- x[, !names(x) %in% names(y)]
  return(list(y, z))
}

答案 3 :(得分:0)

您可以尝试:

testfun <- function(x, y, z){
  y1 <- select(x, y)
  z1 <- select(x, -one_of(z)) 
  return(list(y1, z1)) 
}
testfun(test, "a", "b")
[[1]]
  a
1 1
2 2
3 3

[[2]]
  a c
1 1 1
2 2 2
3 3 3

您还可以使用c

指定更多变量
testfun(test, c("a", "c"), c("b", "a"))