3
votes

I have a data frame with as follows

lower <- c(1,5,15)
upper <-c(5,15,30)
df<-data.frame(lower,upper)

I would like to use dplyr's mutate to create a new variable of the area under the curve of a defined function. The function is as follows.

my_fun <- function(x){y = 1.205016 + 0.03796243 * log(x)}

I am using the integral() function from the pracma package to find the area under the curve. When I use this function on an a pair of upper and lower values it runs with no Errors as follows.

integral(my_fun, 1,5)
[1] 4.973705`

However, when I try to run this same function using dplyr's mutate, I get the following.

new_df <- df %>%
   mutate(new_variable = integral(my_fun, lower, upper))

Error in integral(my_fun, lower, upper) : length(xmin) == 1 is not TRUE

It seems that the integral function must be reading the whole vectors df$lower and df$upperrather than the individual pairs of values 1,5. Is there a solution to this using dplyr's mutate, or should I be looking for other solutions.

I did some looking around and the only instances of this error related to mutate did not seem to address the issue I have here.

1

1 Answers

2
votes

We could use rowwise

library(dplyr)
library(pracma)
df %>%
    rowwise %>%
     mutate(new_variable = integral(my_fun, lower, upper))

-output

# A tibble: 3 x 3
# Rowwise: 
#  lower upper new_variable
#  <dbl> <dbl>        <dbl>
#1     1     5         4.97
#2     5    15        12.9 
#3    15    30        19.8 

Or with map2

library(purrr)
df %>%
     mutate(new_variable = map2_dbl(lower, upper, ~integral(my_fun, .x, .y)))   

-output

#  lower upper new_variable
#1     1     5     4.973705
#2     5    15    12.907107
#3    15    30    19.837273

Or using pmap

df %>%
     mutate(new_variable = pmap_dbl(cur_data(), ~ integral(my_fun, ..1, ..2)))
#  lower upper new_variable
#1     1     5     4.973705
#2     5    15    12.907107
#3    15    30    19.837273

Or using base R

df$new_variable <-  unlist(Map(function(x, y) 
          integral(my_fun, x, y), df$lower, df$upper))

Or using apply from base R

apply(df, 1, function(x) integral(my_fun, x[1], x[2]))
#[1]  4.973705 12.907107 19.837273