Reputation: 145
I am trying to use purrr
to map multiple functions to two inputs. An example is given below but ideally i'd like to extend this to more functions. When trying to do this i'm getting an error that the input is not found, however, even when I try and name inputs in the list of functions this doesn't rectify the problem.
library(yardstick)
library(tidyverse)
funcs <- list(accuracy = yardstick::accuracy_vec,
recall = yardstick::recall_vec)
n <- 1000
x <- as.factor(rbinom(n, 1, 0.5))
y <- as.factor(rbinom(n, 1, 0.5))
df <- tibble(true = rep(list(y), 3),
preds = rep(list(x), 3))
df
#> # A tibble: 3 x 2
#> true preds
#> <list> <list>
#> 1 <int [1,000]> <int [1,000]>
#> 2 <int [1,000]> <int [1,000]>
#> 3 <int [1,000]> <int [1,000]>
df %>% map2_df(.x = true, .y = preds, .f = funcs)
#> Error in map2(.x, .y, .f, ...): object 'true' not found
funcs <- list(accuracy = ~yardstick::accuracy_vec(truth = .x, estimate = .y),
recall = ~yardstick::recall_vec(truth = .x, estimate = .y))
df %>% map2_df(.x = true, .y = preds, .f = funcs)
#> Error in map2(.x, .y, .f, ...): object 'true' not found
Ideally I would end up with something like this:
# A tibble: 3 x 4
true preds accuracy recall
<list> <list> <dbl> <dbl>
1 <int [1,000]> <int [1,000]> 0.7 0.8
2 <int [1,000]> <int [1,000]> 0.7 0.8
3 <int [1,000]> <int [1,000]> 0.7 0.8
Any help is much appreciated, TIA
Upvotes: 3
Views: 1008
Reputation: 388982
I get errors when I pass numeric values to function accuracy_vec
and recall_vec
. I get
Error:
truth
should be a factor but a integer was supplied..
So I change the data to factor.
library(tidyverse)
n <- 1000
x <- rbinom(n, 1, 0.5)
y <- rbinom(n, 1, 0.5)
df <- tibble(true = rep(list(factor(y)), 3),
preds = rep(list(factor(x)), 3))
Secondly, pipes pass value from left-hand side (LHS) as first argument to the function on right-hand side. So when you use df %>% map2_df(.x = true, .y = preds, .f = funcs)
df
is being passed implicitly.
You may write a custom function to return a tibble.
funcs <- function(.x, .y) {
tibble(accuracy = yardstick::accuracy_vec(truth = .x, estimate = .y),
recall = yardstick::recall_vec(truth = .x, estimate = .y))
}
and then use map2_df
to get one dataframe as output.
map2_df(df$true, df$preds, funcs)
Upvotes: 2
Reputation: 10776
You can use nested maps:
df %>%
mutate(map2_dfr(true, preds, ~map_dfc(funcs, do.call, list(.x, .y))))
Upvotes: 2