1

I want to filter a data frame to include rows where the value of any column containing the string "bean" starts with "black" or contains "vanilla."

My code looks like this.

  library(dplyr)
  df2 <- df1 %>%
    filter(
      if_any(
        .cols = contains('bean'),
        grepl(
          pattern = "^black*|*vanilla*",
          ignore.case = T,
          x = .
        )
      )
    )

But that gives me this error:

Error: Problem with `filter()` input `..1`.
x Problem with `across()` input `.fns`.
ℹ Input `.fns` must be NULL, a function, a formula, or a list of functions/formulas.
ℹ Input `..1` is `if_all(...)`.
Run `rlang::last_error()` to see where the error occurred.

Running last_error() gives me this:

<error/dplyr_error>
Problem with `filter()` input `..1`.
x Problem with `across()` input `.fns`.
ℹ Input `.fns` must be NULL, a function, a formula, or a list of functions/formulas.
ℹ Input `..1` is `if_any(...)`.
Backtrace:
Run `rlang::last_trace()` to see the full context.

Running last_trace() gives me this:

<error/dplyr_error>
Problem with `filter()` input `..1`.
x Problem with `across()` input `.fns`.
ℹ Input `.fns` must be NULL, a function, a formula, or a list of functions/formulas.
ℹ Input `..1` is `if_any(...)`.
Backtrace:
     █
  1. ├─`%>%`(...)
  2. ├─dplyr::filter(...)
  3. ├─dplyr:::filter.data.frame(...)
  4. │ └─dplyr:::filter_rows(.data, ...)
  5. │   ├─base::withCallingHandlers(...)
  6. │   └─mask$eval_all_filter(dots, env_filter)
  7. ├─dplyr::if_any(...)
  8. │ └─dplyr::across(...)
  9. │   └─dplyr:::across_setup(...)
 10. │     └─dplyr:::across_setup_impl(...)
 11. │       └─rlang::abort(c("Problem with `across()` input `.fns`.", i = "Input `.fns` must be NULL, a function, a formula, or a list of functions/formulas."))
 12. │         └─rlang:::signal_abort(cnd)
 13. │           └─base::signalCondition(cnd)
 14. └─(function (e) ...

1 Answer 1

2

We need a lambda function (~) as the x is .. The use of * in the pattern implies zero or more characters. Not sure if the OP meant it that way

library(dplyr) # version 1.0.4
df1 %>%
filter(
  if_any(
    .cols = contains('bean'),
    ~ grepl(
      pattern = "^black*|*vanilla*",
      ignore.case = TRUE,
      x = .
    )
  )
)

-output

#   bean_1 bean_2 col3
#1   black velvet    1
#2 vanilla    red    4

Or if we don't specify the x, OP's current code would work because it already specified the pattern and ignore.case as named arguments

df1 %>%
 filter(
  if_any(
    .cols = contains('bean'),
    grepl,
      pattern = "^black*|*vanilla*",
      ignore.case = TRUE
     
    
  )
)

-output

#  bean_1 bean_2 col3
#1   black velvet    1
#2 vanilla    red    4

data

df1 <- data.frame(bean_1 = c('black', 'velvet', 'orange', 'vanilla'),
       bean_2 = c('velvet', 'red', 'green', 'red'), col3 = 1:4)
Sign up to request clarification or add additional context in comments.

2 Comments

What does the tilda mean?
@Username sorry, was away. The ~ is a short form in tidyverse for function(x). it can be otherwise written as function(x) grepl( pattern = "^black*|*vanilla*", ignore.case = TRUE, x = x) which is a lamdba/anonymous function

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.