Francesco
Francesco

Reputation: 35

Automatic creation and use of custom made function in R

I would like to create evaluate different indexes in a for loop cycle. those indexes has different formulas and not always they need to be evaluated. f.i. : my indices to evaluate might be

a=1
b=2
c=5
d=8
IDX1=function(a,b) {result=a+b}
IDX2=function(c,b) {result=c+b}
IDX3=function(d,b) {result=d+b-c}
IDX4=function(a,d) {result=a+d+b+c}

the formulas doesn't really matter

in a data frame I have the iteration number and the indices i need to take at each loop (let's say that I have to evaluate 2 indices for each iteration)

head=c("iter","IndexA","IndexB")
r1=c(1,"IDX1","IDX2")
r2=c(2,"IDX3","IDX4")
r3=c(3,"IDX1","IDX4")
df=as.data.frame(rbind(head,r1,r2,r3))

what I would like to do is within the loop evaluate for each iteration the respective 2 indices, calling automatically the right formula ad feed it with the right arguments

iter 1 : IndexA=IDX1(args)=3  ; IndexB(args)=IDX2(args)=7
iter 2 : IndexA=IDX3(args)=5  ; IndexB(args)=IDX4(args)=16
iter 3 : IndexA=IDX1(args)=3  ; IndexB(args)=IDX4(args)=16

Plese do not answer with "just run all the function and recall the needed result in the loop".

I'm working with big matrix and memory is a problem indeed. I need to evaluate the function within the loop to reduce the usage of memory

I believe that the answer is some what inside this discussion but I can't get trough.

How to create an R function programmatically?

Can somebody explain me 1. how to built a function that can be programmatically changed in a loop? 2. once I have it how can I run the formula and get the result I want? thanks

Upvotes: 2

Views: 149

Answers (1)

Istrel
Istrel

Reputation: 2588

You can use a combination of eval and parse function to call (evaluate) any string as code. First, you have to construct such a string. For this, you can specify your indexes as character strings. For example: IDX1 = "a + b". Then, you can get that value by name with get("IDX1").

Try this code:

# Your preparations
a <- 1
b <- 2
c <- 5
d <- 8
IDX1 <- "a + b"
IDX2 <- "c + b"
IDX3 <- "d + b - c"
IDX4 <- "a + d + b + c"


head = c("iter", "IndexA", "IndexB")
r1 = c(1, "IDX1", "IDX2")
r2 = c(2, "IDX3", "IDX4")
r3 = c(3, "IDX1", "IDX4")
df = as.data.frame(rbind(r1, r2, r3))
colnames(df) <- head

# Loop over df with apply
result <- apply(df, 1, function(x){
    # Construct call string for further evaluation
    IndexA_call <- paste("ia <- ", get(x[2]), sep = "")
    IndexB_call <- paste("ib <- ", get(x[3]), sep = "")

    # eval each call string
    eval(parse(text = IndexA_call))
    eval(parse(text = IndexB_call))

    x[2:3] <- c(ia, ib)
    return(as.numeric(x))
})

result <- t(result)
colnames(result) <- head
print(result)

This gives:

   iter IndexA IndexB
r1    1      3      7
r2    2      5     16
r3    3      3     16

Upvotes: 1

Related Questions