Number one, extremely happy to have the new features for filter and/or mutate() with if_any/if_all!!! This feature was not something I expected but am so excited to have!!!
🥳
There is one problem I'd like to raise and one question:
Problem: The error message for using if_any() without a column selector results in some potentially bad recommendations (related to my question as well).
Question: What is the "correct" way of select-ing columns based on values within that column?
While I understand the use of if_any with filter(), I'm also interested in the similar option for select(). when cleaning data or working with "wide" data that I'm putting into a table I fairly often want to select() specific columns that contain a specific value/string/range/etc. IE just knowing it's numeric or text is not sufficient, but rather I'm interested in specifics of the column's contents.
I have a reprex below that shows some of my testing steps in trying to answer this question.
library(dplyr, warn.conflicts = FALSE)
library(palmerpenguins)
#> Warning: package 'palmerpenguins' was built under R version 4.0.2
# Filter specific columns
ex1 <- penguins %>%
filter(if_any(contains("bill"), ~.x == 39.1| .x == 18.7))
ex1
#> # A tibble: 6 x 8
#> species island bill_length_mm bill_depth_mm flipper_length_… body_mass_g sex
#> <fct> <fct> <dbl> <dbl> <int> <int> <fct>
#> 1 Adelie Torge… 39.1 18.7 181 3750 male
#> 2 Adelie Biscoe 37.7 18.7 180 3600 male
#> 3 Adelie Dream 39 18.7 185 3650 male
#> 4 Chinst… Dream 45.4 18.7 188 3525 fema…
#> 5 Chinst… Dream 51.5 18.7 187 3250 male
#> 6 Chinst… Dream 50.2 18.7 198 3775 fema…
#> # … with 1 more variable: year <int>
# I realize this is a toy example
# that could be solved by normal filter
ex2 <- penguins %>%
filter(bill_length_mm == 39.1| bill_depth_mm == 18.7)
all.equal(ex1, ex2)
#> [1] TRUE
# Skip tidyselect ---------------------------------------------------------
# What happens when you don't indicate tidyselect or colname?
# Throws a useful error but in this case leads down
# a not very useful path
penguins %>%
filter(if_any(~.x == 39.1))
#> Error: Problem with `filter()` input `..1`.
#> x Formula shorthand must be wrapped in `where()`.
#>
#> # Bad
#> data %>% select(~.x == 39.1)
#>
#> # Good
#> data %>% select(where(~.x == 39.1))
#> ℹ Input `..1` is `if_any(~.x == 39.1)`.
# So then let's follow the recommendation of:
# data %>% select(where(~.x == 39.1))
# this fails because it's not vectorized I believe?
penguins %>%
select(where(~.x == 39.1))
#> Error: `where()` must be used with functions that return `TRUE` or `FALSE`.
# Still fails with everything() indicated
penguins %>%
select(where(if_any(everything(), ~.x == 39.1)))
#> Error: `across()` must only be used inside dplyr verbs.
# Use base::any ---------------------------------------------------------
# So for this behavior, I want to select a specific column
# by values present in that column
# this WILL work if you use base::any() without any extra work!!!
# But I wanted to make sure this is a good idea?
penguins %>%
select(where(~any(.x == 36.7, na.rm = TRUE)))
#> # A tibble: 344 x 1
#> bill_length_mm
#> <dbl>
#> 1 39.1
#> 2 39.5
#> 3 40.3
#> 4 NA
#> 5 36.7
#> 6 39.3
#> 7 38.9
#> 8 39.2
#> 9 34.1
#> 10 42
#> # … with 334 more rows
Created on 2021-02-03 by the reprex package (v0.3.0)
Number one, extremely happy to have the new features for
filterand/ormutate()withif_any/if_all!!! This feature was not something I expected but am so excited to have!!!🥳
There is one problem I'd like to raise and one question:
Problem: The error message for using
if_any()without a column selector results in some potentially bad recommendations (related to my question as well).Question: What is the "correct" way of
select-ing columns based on values within that column?While I understand the use of
if_anywithfilter(), I'm also interested in the similar option forselect(). when cleaning data or working with "wide" data that I'm putting into a table I fairly often want toselect()specific columns that contain a specific value/string/range/etc. IE just knowing it's numeric or text is not sufficient, but rather I'm interested in specifics of the column's contents.I have a reprex below that shows some of my testing steps in trying to answer this question.
Created on 2021-02-03 by the reprex package (v0.3.0)