Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible scoping issue when rlang used within purrr #1768

Closed
bguiastr opened this issue Dec 27, 2024 · 1 comment
Closed

Possible scoping issue when rlang used within purrr #1768

bguiastr opened this issue Dec 27, 2024 · 1 comment

Comments

@bguiastr
Copy link

bguiastr commented Dec 27, 2024

Background

I keep falling into an issue with rlang/purrr which to me could be a potential bug in the way the scoping is done in rlang when used together with purrr.

To give you a bit of context as of why I came up with the code below, I am generating skeleton data frames with list columns using tibble for which each row represents one "scenario" which would correspond to either evaluation of a models, a covariates, or a new dataset. More specifically, in the example below I needed to pre-process modeling data amongst other things by filtering based on specific flags on the fly.

The issue

library(dplyr)
library(purrr)
library(tibble)
library(rlang)

df <- tibble(
  scenario = 1:2, 
  flag     = c("vs", "am")
) %>%
  mutate(data = list(mtcars)) %>% 
  group_by(scenario) %>% 
  mutate(
    results = map2(
      .x = data,
      .y = flag,
      .f = ~{
        filter(.x, !!sym(.y) == 0) # This is where the issue happens
      }
    )
  )
#> Error: object '.y' not found

Created on 2024-12-27 with reprex v2.1.1

What makes me think is it a scoping issue that I could not even debug this code using browser() as shown below, even though browser() is called before the record with the issue. Note that commenting out the filter() record makes browser() work again.

df <- tibble(
  scenario = 1:2, 
  flag     = c("vs", "am")
) %>%
  mutate(data = list(mtcars)) %>% 
  group_by(scenario) %>% 
  mutate(
    results = map2(
      .x = data,
      .y = flag,
      .f = ~{
        browser()
        filter(.x, !!sym(.y) == 0) # This is where the issue happens
      }
    )
  )
#> Error: object '.y' not found

Created on 2024-12-27 with reprex v2.1.1

Workaround

For now the only workaround I could find is to move away from rlang and stick with base R within purrr::map.

Note I also tried to replace !!sym(.y) by .data[[.y]] without success.

df <- tibble(
  scenario  = 1:2, 
  flag      = c("vs", "am")
) %>%
  mutate(data = list(mtcars)) %>% 
  group_by(scenario) %>% 
  mutate(
    results = map2(
      .x = data,
      .y = flag,
      .f = ~{
        .x[.x[, .y] == 0, ] # Workaround
      }
    )
  )

Created on 2024-12-27 with reprex v2.1.1

@lionel-
Copy link
Member

lionel- commented Jan 6, 2025

Tracked in #845

The problem is that the outermost tidyeval function (in this case mutate(), not filter()) is the one doing the injection. So the timing is too soon. Currently you'll have to move the lambda to a named function to prevent this early injection (or use an ugly trick like !!quote(filter(...))).

@lionel- lionel- closed this as completed Jan 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants