purrr::map and the pipes

Hi All,

I am, as explained yesterday, in the process of learning purrr.
So far, so very good, it is a wonderful tool.

But the thing that crosses me is the documentation, and notably when dealing with the pipes.

As soon as R has issued the native pipe, I switched from magrittr to the R native pipe and replaced the old pipe by the official one.
But the thing with purr's articles and, more generally, the code samples on this forum, Stackoverflow, etc. is that they still use the magrittr pipe -- and for a good reason: they were written before the issuance of the native pipe.
But the parameter passing with the old pipe has become irrelevant to the native one and won't work any longer (notably: .$column).

Moreover, R 4.10 has introduced the anonymous function notation \(x), which has added a new combinatorial obsolescence to the documentation...

IMO, the situation with the pipes has considerably increased the difficulty to learn purrr for lack of a steadfast documentation.

Let's be more practical. I am trying to do the following:

  1. Load a tibble with two columns
  2. Pass both columns of the tibble to purrr:walk2 and use the native pipe to do so.

For example, I would like to assign emojis each to their own global variable:

require(emoji)
theemo <- tibble::tribble(
    ~var, ~emo,
    "blksqr", "black_large_square",
    "blusqr", "blue_square",
    "grnsqr", "green_square",
)
purrr::walk2(
    .x = theemo$var,
    .y = theemo$emo,
    .f = ~ assign(x = .x, value = emoji::emoji(.y), envir = globalenv())
)

I have tried everything but was unable to pipe the emoji definition tibble to walk2.
For example, this won't work (when it does in different contexts) :

require(emoji)
tibble::tribble(
    ~var, ~emo,
    "blksqr", "black_large_square",
    "blusqr", "blue_square",
    "grnsqr", "green_square",
) |>
purrr::walk2(
    .x = var,
    .y = emo,
    .f = ~ assign(x = .x, value = emoji::emoji(.y), envir = globalenv())
)

It is not a big deal but it would avoid creating a named variable (theemo = the tibble) and would tighten my code.

Please help.

Thanks,
Stephen

purrr doesn't use data masking and won't be able to access your data like that. purrr is meant to be used with actual vectors.

There're different ways of achieving what you want which implies transforming your data first. E.g.:

tibble::tribble(
  ~var, ~emo,
  "blksqr", "black_large_square",
  "blusqr", "blue_square",
  "grnsqr", "green_square",
) |>
  as.list() |> 
  purrr::list_transpose() |> 
  purrr::walk(\(.x) {
    assign(x = .x[["var"]], value = emoji::emoji(.x[["emo"]]), envir = globalenv())
  })

I don't know what you're trying to do but it's almost always a bad idea to generate variables like this, more so in the global environment because it's quite implicit with a risk of overwritting existing objects.

1 Like

Thank you @arangaca for this comprehensive response (and advice).
This was merely a test, while learning purr. So, no worries ;o))

Can I ask you something though: why is the conversion to a list doing the trick?

Thx,
Stephen

It's not the list conversion that does the trick but the data transposition, which in the case of purrr::list_transpose() only accepts a list.

Again, there're many approaches. Here's another approach that doesn't convert the data to a list:

tibble::tribble(
  ~var, ~emo,
  "blksqr", "black_large_square",
  "blusqr", "blue_square",
  "grnsqr", "green_square",
) |> 
  dplyr::reframe(out = rlang::set_names(var, emo)) |> 
  dplyr::pull() |> 
  purrr::iwalk(\(value, key) {
    assign(value, emoji::emoji(key), globalenv())
  })

For this you'd generally just pick another functional, pmap() / pwalk():

tibble::tribble(
  ~var, ~emo,
  "blksqr", "black_large_square",
  "blusqr", "blue_square",
  "grnsqr", "green_square",
) |>
purrr::pwalk(
  \(var, emo) assign(x = var, value = emoji::emoji(emo), envir = globalenv())
)
ls(pattern = "sqr$") |> mget() |> unlist()
#> blksqr blusqr grnsqr 
#>   "⬛"   "🟦"   "🟩"

Hi all,
I am always so much in awe of the creative ways one can achieve their results in R.
Wonderful, thank you!

Stephen