littleworth
littleworth

Reputation: 5169

How to properly pass a parameter from a tibble into a function via purrr::pmap

I have the following function, it simply concatenates series of string

test_func <- function(cellTypeA, cellTypeB, other_text) { 
   paste(cellTypeA, " ", cellTypeB, " ", other_text)
}

And I have a set of parameters packed as a tibble.

param_df <- structure(list(cellTypeA = c("Cluster11", "Cluster2", "Cluster4"
), cellTypeB = c("Cluster11", "Cluster2", "Cluster4")), row.names = c(NA, 
-3L), class = "data.frame")

That looks like this:

  cellTypeA cellTypeB
1 Cluster11 Cluster11
2  Cluster2  Cluster2
3  Cluster4  Cluster4

I'd like to iterate the function over the parameter set above using purrr::pmap. But why this doesn't work?

library(tidyverse)
param_df %>%
 pmap(~test_func(.cellTypeA, .cellTypeB, "FOO"))

It gives me:

Error in cat(cellTypeA, " ", cellTypeB) : object '.cellTypeA' not found 

I expect the result to look like:

[[1]]
[1] Cluster11 Cluster11 FOO

[[2]]
[1] Cluster2  Cluster2 FOO

[[3]]
[1] Cluster4  Cluster4 FOO

Upvotes: 2

Views: 354

Answers (2)

eipi10
eipi10

Reputation: 93841

With pmap, you refer back to the two columns of the input list (or data frame) with .x. and .y. So the code would be:

param_df %>%
  pmap(~test_func(.x, .y, other_text="FOO"))
[[1]]
[1] "Cluster11   Cluster11   FOO"

[[2]]
[1] "Cluster2   Cluster2   FOO"

[[3]]
[1] "Cluster4   Cluster4   FOO"

You can also refer back to the input columns using numbers, which is helpful if you have more than two columns of parameters. For example:

test_func2 <- function(col1, col2, col3, other_text) { 
  paste(col1, col2, col3, other_text)
}

param_df %>%
  mutate(cellTypeC = paste0("Cluster", 10:12)) %>% 
  pmap(~test_func2(..1, ..2, ..3, other_text="FOO"))
[[1]]
[1] "Cluster11 Cluster11 Cluster10 FOO"

[[2]]
[1] "Cluster2 Cluster2 Cluster11 FOO"

[[3]]
[1] "Cluster4 Cluster4 Cluster12 FOO"

If you want to be able to pass any number of columns as parameters, you can generalize the function as follows:

test_func3 <- function(..., other_text) { 
  paste(paste(..., sep=" "), other_text, sep=" ")
}

param_df %>%
  pmap(~test_func3(..., other_text="FOO"))
[[1]]
[1] "Cluster11   Cluster11   FOO"

[[2]]
[1] "Cluster2   Cluster2   FOO"

[[3]]
[1] "Cluster4   Cluster4   FOO"
iris[1:2, ] %>%
  pmap(~test_func3(..., other_text="FOO"))
[[1]]
[1] "5.1 3.5 1.4 0.2 setosa FOO"

[[2]]
[1] "4.9 3 1.4 0.2 setosa FOO"

Upvotes: 2

Humpelstielzchen
Humpelstielzchen

Reputation: 6441

cat() is the wrong function. It just prints to the console. This is one option:

test_func <- function(cellTypeA, cellTypeB, other_text) { 
                paste(cellTypeA, " ", cellTypeB, " ", other_text)
  }

pmap(param_df, ~data.frame(string = test_func(..., "FOO")))

[[1]]
                       string
1 Cluster11   Cluster11   FOO

[[2]]
                     string
1 Cluster2   Cluster2   FOO

[[3]]
                     string
1 Cluster4   Cluster4   FOO

Upvotes: 1

Related Questions