1

I have a dataframe "data", and want to calculate around 30 functions f(CS). The goal is to find CS for each function f(CS) with uniroot. I'm looking for a loop, that generates the functions f(CS) and the results of the functions (meaning the CS's).

Related questions: R - Naming multiple functions in a for loop and Multiple functions in for loop

The functions should have different names (function_1, function_2, function_3 etc.), and each function uses values from different rows from the dataframe "data". I tried my best to create a minimum reproducible example:

data <- data.frame(A=c(154,154,154,154,110154,102500,0,0,0,0,205200,0,0,0,0), 
                   B=c(-0.647, -0.738, -0.749, -0.691, -0.600, 2.455, 2.358, 2.289, 2.264, 2.267, 2.455, 2.358, 2.289, 2.264, 2.267))

function_1 <- function(CS){
          sum(data$A[1:5]/(1+data$B[1:5]/100+CS/10000)^(1:5) - 100000)
      }

function_2 <- function(CS){
      sum(data$A[6:10]/(1+data$B[6:10]/100+CS/10000)^(1:5) - 100000)
  }

function_3 <- function(CS){
      sum(data$A[11:15]/(1+data$B[11:15]/100+CS/10000)^(1:5) - 200000)
  }

Please note, that the constant in function_3 (200000) isnt a typo. As I mentioned, im calculating the roots with uniroot:

uniroot(function_1, c(-1000,1000))$root #267.3119
uniroot(function_2, c(-1000,1000))$root #4.500001
uniroot(function_3, c(-1000,1000))$root #14.5

I tried to use two for loops as below:

for (i in seq(from = 1, to = nrow(data)/5)){
noquote(paste0("function_",i,"")) <- function(CS){
           sum(data$A[1:5]/(1+data$B[1:5]/100+CS/10000)^(1:5))
   }
 }

for (i in seq(from = 1, to = nrow(data)/5)){
    uniroot(noquote(paste0("function_",i,")), c(-1000,1000))$root
  }

I don't know how to implement the changing constant and the changing function name, as noquote(paste0()) does not seem to work. Please let me know if you need any further information.

1
  • 2
    Use get() rather than noquote(). The latter only hides quotes while printing, it does not create variable names. The former will return the value of a variable given the a character values with its name. But really it would be better to just stored your functions in a named list and avoid get() altogether. That's a much more R-like way to do things. Commented Oct 23, 2019 at 15:25

1 Answer 1

1

You're close, but this isn't quite what noquote is for. Instead, use a combination of assign and get, like this:

for (i in seq(from = 1, to = nrow(data)/5)){
   assign(paste0("function_",i)), function(CS){
           sum(data$A[1:5]/(1+data$B[1:5]/100+CS/10000)^(1:5))
   }
 }

for (i in seq(from = 1, to = nrow(data)/5)){
    uniroot(get(paste0("function_",i)), c(-1000,1000))$root
}

However, I'm not sure the first loop in your example actually recreates the desired functions that you manually listed in the first code chunk in your question. Shouldn't the indexing of data change too? Like this?

for (i in seq(from = 1, to = nrow(data)/5)){
   indices <- (1+(i-1)*5):(5+(i-1)*5)
   assign(paste0("function_",i,"")), function(CS){
           sum(data$A[indices ]/(1+data$B[indices]/100+CS/10000)^(1:5))
   }
 }

Anyway, I'm sure others will be quick to say that you can probably find a way around having to loop over object names like this. Most would argue that best practices would be to manually assign the function and then make it more flexible. In the example you provided, you could construct the function so that it takes the indices as an argument, then you just have one function that you use in a variety of ways:

flexibleFunction <- function(CS, indices){
      sum(data$A[indices]/(1+data$B[indices]/100+CS/10000)^(1:5) - 100000)
  }

uniroot(flexibleFunction , c(-1000,1000), 1:5)$root
uniroot(flexibleFunction , c(-1000,1000), 6:10)$root
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.