Reputation: 3176
I'm trying to do a calculation using an home made function inside a mutate
call and it's not doing what I'm expecting it to do.
Here is a reproducible example:
library(dplyr)
#the data
dd <- structure(list(fire_zone = c("ET", "EJB", "WJB"), base_med = c(1, 1, 2)), class = "data.frame", row.names = c(NA, -3L))
# my home made function
med2lambda <- function(med) polyroot(c(-0.02, 1/3 - med, 1)) %>% {suppressWarnings(as.numeric(.))} %>% max
So, what my function does is to estimate the lambda associated to the median from a Poisson distribution by calculating the root of a quadratic function. Despite the long explanation, it's actually pretty basic:
med2lambda(1)
[1] 0.695426
med2lambda(2)
[1] 1.678581
Now, I want to use it in a mutate
call to add a field giving the lambda associated to each median in the table:
dd %>% mutate(lambda = med2lambda(base_med), log = log(base_med))
fire_zone base_med lambda log
1 ET 1 2.128966 0.0000000
2 EJB 1 2.128966 0.0000000
3 WJB 2 2.128966 0.6931472
The result is wrong, mutate actually gives me the results of:
med2lambda(dd$base_med)
[1] 2.128966
I've added the log
call in the mutate
to give an idea of what it should do. log
works great in the mutate
as it is called element by element.
Any insight about this behavior would be appreciated.
Upvotes: 0
Views: 85
Reputation: 50738
You need to allow med2lambda
to take vectors instead of scalars.
One possibility is to use Vectorize
:
med2lambda.vectorised <- Vectorize(med2lambda)
dd %>% mutate(lambda = med2lambda.vectorised(base_med), log = log(base_med))
# fire_zone base_med lambda log
#1 ET 1 0.695426 0.0000000
#2 EJB 1 0.695426 0.0000000
#3 WJB 2 1.678581 0.6931472
Alternatively, you could rewrite med2lambda
to take a vector as argument:
med2lambda2 <- function(med) sapply(med, function(x)
polyroot(c(-0.02, 1/3 - x, 1)) %>% {suppressWarnings(as.numeric(.))} %>% max)
dd %>% mutate(lambda = med2lambda2(base_med), log = log(base_med))
# fire_zone base_med lambda log
#1 ET 1 0.695426 0.0000000
#2 EJB 1 0.695426 0.0000000
#3 WJB 2 1.678581 0.6931472
Upvotes: 2
Reputation: 887901
We can use map
library(tidyverse)
dd %>%
mutate(lambda = map_dbl(base_med, med2lambda), log = log(base_med))
Upvotes: 0