Transform a list of lists into a differently arranged list of lists to use for pmap

66 Views Asked by At

I've been struggling really hard to get pmap() to work and misunderstood the structure of the list that I am supposed to feed it.

Basically, I ended up with a list of lists, before, but it's not in the correct arrangement for pmap.

Here's a minimum repro of what it's like:

before <- list(
  list(
    tibble(a = c(10:13), b = c(13:16), c = c(17:20)),
    tibble(d = c(10:13), e = c(13:16)),
    tibble(f = c(10:13))
  ),
  list(
    tibble(a = c(10:13), b = c(13:16), c = c(17:20)),
    tibble(d = c(21:24), e = c(25:28)),
    tibble(f = c(21:24))
  ),
  list(
    tibble(a = c(31:34), b = c(35:38), c = c(20:23)),
    tibble(d = c(31:34), e = c(35:38)),
    tibble(f = c(31:34))
  ),
  list(
    tibble(a = c(40:43), b = c(43:46), c = c(47:50)),
    tibble(d = c(40:43), e = c(43:46)),
    tibble(f = c(40:43))
  )
)

However, that's wrong for what to use as the .l argument in pmap().

I think would like to transform it into a list of lists like below, after.

after <- list(
  list(
    tibble(a = c(10:13), b = c(13:16), c = c(17:20)),
    tibble(a = c(10:13), b = c(13:16), c = c(17:20)),
    tibble(a = c(31:34), b = c(35:38), c = c(20:23)),
    tibble(a = c(40:43), b = c(43:46), c = c(47:50))
  ),
  list(
    tibble(d = c(10:13), e = c(13:16)),
    tibble(d = c(21:24), e = c(25:28)),
    tibble(d = c(31:34), e = c(35:38)),
    tibble(d = c(40:43), e = c(43:46))
  ),
  list(
    tibble(f = c(10:13)),
    tibble(f = c(21:24)),
    tibble(f = c(31:34)),
    tibble(f = c(40:43))
  )
)

That way, I could perform this...

x <- pmap(after, my_func) 

Where my_func is a function that takes 3 different tibbles as arguments. It's actually a function that creates complicated ggplots.

The questions are:

  • How can I transform before to after?
  • Is after in the right form to use pmap to map to a function that takes 3 tibbles as arguments?
3

There are 3 best solutions below

1
G. Grothendieck On BEST ANSWER

Use tranpose from purrr:

library(purrr)

after2 <- tranpose(before)

identical(after, after2)
## [1] TRUE
0
zx8754 On

Using lapply:

out <- lapply(1:3, \(i) lapply(before, "[[", i))

#check
identical(out, after)
# [1] TRUE
0
Andre Wildberg On

With pmap use arguments that fit the list content

before %>% purrr::pmap(\(x, y, z, k) list(x, y, z, k))
[[1]]
[[1]][[1]]
# A tibble: 4 × 3
      a     b     c
  <int> <int> <int>
1    10    13    17
2    11    14    18
3    12    15    19
4    13    16    20

[[1]][[2]]
# A tibble: 4 × 3
      a     b     c
  <int> <int> <int>
1    10    13    17
2    11    14    18
3    12    15    19
4    13    16    20
...

Test on after

identical(after, before %>% purrr::pmap(\(x, y, z, k) list(x, y, z, k)))
[1] TRUE