Re rowwise(); best practice when it is useful to access the parent environment for some row-wise operation?


#1

Maybe this is a silly question, but what about when it is useful to access the parent environment for some row-wise operation?

For instance, lets say you have a variable v1 indicating which of the groupA, groupB, ..., groupX variable's value you want in a new variable var.

Is there a more convenient way of solving this problem without a lot of code?

With rowwise():


df <- tribble(
  ~groupA, ~groupB, ~v1,
  "A","C","groupB",
  "A","D","groupB",
  "A","D","groupA"
)

df %>%
  rowwise() %>%
  mutate(newvar = get(v1)) %>%
  ungroup()

#> # A tibble: 3 x 4
#>   groupA groupB v1     newvar
#>   <chr>  <chr>  <chr>  <chr> 
#> 1 A      C      groupB C     
#> 2 A      D      groupB D     
#> 3 A      D      groupA A     

This doesn't work with map(?):


df %>%
  mutate(newvar = map_chr(v1, get))

#>  Error in mutate_impl(.data, dots) : 
#>  Evaluation error: object 'groupB' not found.

Though this particular problem is perhaps solvable with gather():


df %>%
  left_join(
    df %>%
      gather(key, newvar, -v1) %>%
      filter(key == v1) %>%
      select(-key),
    by = "v1")

Dplyr: Alternatives to rowwise
#2

well this totally breaks the functional paradigm and and creates a non-pure function. So not too shocking that it no longer works with a package which is named after pure-r :wink:


#3

My point was not that it should work with a map function.

The thread is called "alternatives to rowwise" -- I was just wondering if there were any obvious alternatives in this case.

:slight_smile:


#5

I figured this was an environment issue, so I thought I could pass get some help, but I failed. Maybe we can't force map to reach outside of its environment? I'm not sure.

My failed attempt:

df %>%
  mutate(data = pmap(list(x = v1, pos=1), get))

#6

This works but I must say this doesn't feel like a problem that's come up for me.

library(tidyverse)

df <- tribble(
  ~groupA, ~groupB, ~v1,
  "A","C","groupB",
  "A","D","groupB",
  "A","D","groupA"
)

df %>%
  rowwise() %>%
  mutate(newvar = get(v1)) %>%
  ungroup()
#> # A tibble: 3 x 4
#>   groupA groupB v1     newvar
#>   <chr>  <chr>  <chr>  <chr> 
#> 1 A      C      groupB C     
#> 2 A      D      groupB D     
#> 3 A      D      groupA A

df %>% 
  mutate(newvar = pmap_chr(., function(v1, ...) list(...)[[v1]]))
#> # A tibble: 3 x 4
#>   groupA groupB v1     newvar
#>   <chr>  <chr>  <chr>  <chr> 
#> 1 A      C      groupB C     
#> 2 A      D      groupB D     
#> 3 A      D      groupA A

#7

Oh, I see what you did there. Thanks!

I'll admit, this is the only time I have had this problem.


#8

Maybe this is a silly question, but what about when it is useful to access the parent environment for some row-wise operation?

Since we're discussing it, we should probably clarify this. I wouldn't say that the example requires access to the parent environment. I'd say you want a specific type of access to members of the tuple that purrr::pmap() operates on. It's not the type of access that purrr::pmap() is optimized for. I think this is OK, because I think this is a pretty unusual need. The tuple is provided to .f as "loose parts", not packaged into a named list. So if you want to index into it by name, we have to put it into a list.