'How to use dynamic tidy-select expressions in dplyr::select()?
I need to select variables dynamically on multiple expressions. Consider the following example:
library(tidyverse)
set.seed(42)
df <- tibble(
grey_dog = runif(n = 69),
white_bear = runif(n = 69),
blue_oyster = runif(n = 69),
white_lobster = runif(n = 69),
green_dog = runif(n = 69)
)
df %>%
dplyr::select(
(contains("dog") & contains("green")) |
(contains("white") & contains("bear"))
)
Instead of explicitly selecting, I have vectors containing the information I want to base my selection on:
x <- c(green = "dog", white = "bear")
So I was hoping to concatenate a string that can be used as a tidy-select:
s <- paste0("(", paste0("contains(", names(x),") & contains(", x, ")"), ")", collapse = " | ")
dplyr::select(df, s)
This fails with:
Error: Can't subset columns that don't exist.
x Column `(contains(green) & contains(dog)) | (contains(white) & contains(bear))` doesn't exist.
Run `rlang::last_error()` to see where the error occurred.
Any ideas on how to accomplish this?
Solution 1:[1]
@MrFlick's answer is the way to go for building a tidyselect expression.
However, since you’re building the selection programmatically already: instead of a tidyselect expression, it might be easier to just do the corresponding computations on the names yourself.
library(purrr)
set.seed(42)
df <- data.frame(
grey_dog = runif(n = 5),
white_bear = runif(n = 5),
blue_oyster = runif(n = 5),
white_lobster = runif(n = 5),
green_dog = runif(n = 5)
)
x <- list(
c("green", "dog"),
c("white", "bear")
)
sel <- x |>
map(sapply, grepl, names(df)) |>
map(apply, 1, all) |>
reduce(`|`)
df[, sel]
#> white_bear green_dog
#> 1 0.5190959 0.90403139
#> 2 0.7365883 0.13871017
#> 3 0.1346666 0.98889173
#> 4 0.6569923 0.94666823
#> 5 0.7050648 0.08243756
Or, you could apply the helpers inside the selecting function with map() and then do the set
operatins corresponding to & and | in a similar sequence of steps:
df |>
dplyr::select(
x |>
map(map, contains) |>
map(reduce, intersect) |>
reduce(union)
)
#> green_dog white_bear
#> 1 0.90403139 0.5190959
#> 2 0.13871017 0.7365883
#> 3 0.98889173 0.1346666
#> 4 0.94666823 0.6569923
#> 5 0.08243756 0.7050648
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
