dplyr: deselecting columns given by

送分小仙女□ 提交于 2020-01-03 09:10:11

问题


How can I deselect columns given in the ... argument of a self written function. (I also need to select the columns at another point, so just specifying the columns with - in ... does not solve my problem.)

Any soltions are apreciated, select-helpers, manipulating quosures or expressions, ...

# 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)

回答1:


These easiest solution would be to select the positive columns, and then compare names to figure out which columns to drop, as in this answer.

To work on the dots directly,

  1. We will capture them in a list of quosures (quos).
  2. Unquote and splice the dots in with UQS for the positive selection.
  3. Do the same thing inside of c() so that we have a vector of selection.
  4. Negate that vector to do the negative selection.

This is the transformation described by (3) and (4).

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

The full solution then would be

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

Test on selection helpers.

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



回答2:


You can use this trick with 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



回答3:


What about that one?

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



回答4:


You can try:

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

You can also specify more variables using c

testfun(test, c("a", "c"), c("b", "a"))


来源:https://stackoverflow.com/questions/46828296/dplyr-deselecting-columns-given-by

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!