Skip to content

Possible scoping issue when rlang used within purrr #1768

@bguiastr

Description

@bguiastr

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions