A year ago I already wrote an article how to iterate over the rows of a data.frame.
Now I’ve run into another special case. Last year we used pmap_dfr() to pass
each element of a row as single parameter to our custom function.
But what should you do if your function accepts a data.frame (or list) as one
single parameter?
The function …
But let’s look at our example first:
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 | my_function <- function(repeated = 1, text = "a", number_rows = 2) {
  row <- data.frame(
    `repeated` = repeated,
    `text`   = text,
    `number_rows`  = number_rows, 
    generated_text = paste(replicate(repeated, text), collapse = "")
  )
  return(do.call("rbind", replicate(number_rows, row, simplify = FALSE)))
}
my_function(3, "Hello ", 4)
 | 
 
| 1
2
3
4
5
 | ##   repeated   text number_rows     generated_text
## 1        3 Hello            4 Hello Hello Hello 
## 2        3 Hello            4 Hello Hello Hello 
## 3        3 Hello            4 Hello Hello Hello 
## 4        3 Hello            4 Hello Hello Hello
 | 
 
Let’s change this function a little bit:
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
 | my_new_function <- function(input_data) {
  row <- data.frame(
    `repeated` = input_data$repeated,
    `text`   = input_data$text,
    `number_rows`  = input_data$number_rows, 
    generated_text = paste(replicate(input_data$repeated, input_data$text), collapse = "")
  )
  return(do.call("rbind", replicate(input_data$number_rows, row, simplify = FALSE)))
}
input_data <- data.frame(
  repeated = 3,
  text = "Hello ",
  number_rows = 4
)
my_new_function(input_data)
 | 
 
| 1
2
3
4
5
 | ##   repeated   text number_rows     generated_text
## 1        3 Hello            4 Hello Hello Hello 
## 2        3 Hello            4 Hello Hello Hello 
## 3        3 Hello            4 Hello Hello Hello 
## 4        3 Hello            4 Hello Hello Hello
 | 
 
… and its parameters
Now we want to call the function my_new_function with each row of the
following data.frame as parameter:
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 | options(tidyverse.quiet = TRUE)
library(tidyverse, warn.conflicts = FALSE)
parameters <- tribble(
  ~repeated, ~text, ~number_rows,
  1, "one", 3,
  2, "two", 2,
  3, "three", 1
) %>% 
  as.data.frame()
parameters
 | 
 
| 1
2
3
4
 | ##   repeated  text number_rows
## 1        1   one           3
## 2        2   two           2
## 3        3 three           1
 | 
 
Iterating again
Using purrr::pmap_dfr() won’t work because our function expects one single
argument.
So we use purrr::pmap() to convert each row into a data.frame and combine
these data.frames to a list. Then we can use purrr::map_dfr().
| 1
2
3
 | parameters %>% 
  purrr::pmap(data.frame) %>% 
  purrr::map_dfr(my_new_function)
 | 
 
| 1
2
3
4
5
6
7
 | ##   repeated  text number_rows  generated_text
## 1        1   one           3             one
## 2        1   one           3             one
## 3        1   one           3             one
## 4        2   two           2          twotwo
## 5        2   two           2          twotwo
## 6        3 three           1 threethreethree
 | 
 
Notes
When I had found the above solution for my problem I googled for a solution
with one single purrr function call. During this search I found this
page
by Jenny Bryan who is very inspiring for all
purrr related stuff.