YAQ
YAQ

Reputation: 11

call a function based on variable

i have a dataframe like this:

NAME    ALPHA   BETA    GAMMA DELTA CONSTANT    FUNCTION   ANSWER

A   1   2   3   4   5   F1

B   6   7   8   9   10  F2

C   11  12  13  14  15  F3

D   16  17  18  19  20  F4

E   20  21  22  23  24  F5

F   25  26  27  28  29  F6

G   0.3 0.7 1.0 1.3 1.7 F1

H   2.0 2.3 2.7 3.0 3.3 F2

I   3.7 4.0 4.3 4.7 5.0 F3

J   5.3 5.7 6.0 6.3 6.7 F4

K   6.7 7.0 7.3 7.7 8.0 F5

L   8.3 8.7 9.0 9.3 9.7 F6

M   0.1 0.2 0.3 0.4 0.6 F1

The function i need to apply is defined in the Function column.

Function are predefined equations such as

F1<- function(ALPHA,BETA,GAMMA,DELTA,CONSTANT){
  ((ALPHA * CONSTANT^ 2) + (BETA * SPEED) + GAMMA+ (DELTA * LOG(CONSTANT)) 
}

I want to be able apply the equation in Function column for each row and the result should go into the answer column.

we have a few thousand rows and there are around 50 types of functions.

Is there a way to do this?

Many thanks

Upvotes: 1

Views: 60

Answers (2)

langtang
langtang

Reputation: 24877

Let say df is your dataframe, and you have all the functions F1, F2, F3, F4, F5 well defined. Note, this requires that all the functions have signatures that can accept these five parameters, and are well defined. For example, if I adjust your F1 function (replace LOG with log, and parameter SPEED=0, and for illustrative purposes only, set F2, F3, F4, and F5, all to be the same function (I understand all yours will be different functions), the the following code

library(data.table)
setDT(df)

# fix F1
F1<- function(ALPHA,BETA,GAMMA,DELTA,CONSTANT, SPEED=0) {
  ((ALPHA * CONSTANT^ 2) + (BETA * SPEED) + GAMMA + (DELTA * log(CONSTANT)))
}

# for illustration, defined all other function as F1
F2 <- F3 <- F4 <-F5 <- F6 <-  F1

# get answer, by row
df[, ANSWER:=get(FUNCTION)(ALPHA, BETA, GAMMA, DELTA, CONSTANT), by=seq(1,nrow(df))]

will produce the following output

    NAME ALPHA BETA GAMMA DELTA CONSTANT FUNCTION       ANSWER
 1:    A   1.0  2.0   3.0   4.0      5.0       F1 3.443775e+01
 2:    B   6.0  7.0   8.0   9.0     10.0       F2 6.287233e+02
 3:    C  11.0 12.0  13.0  14.0     15.0       F3 2.525913e+03
 4:    D  16.0 17.0  18.0  19.0     20.0       F4 6.474919e+03
 5:    E  20.0 21.0  22.0  23.0     24.0       F5 1.161510e+04
 6:    F  25.0 26.0  27.0  28.0     29.0       F6 2.114628e+04
 7:    G   0.3  0.7   1.0   1.3      1.7       F1 2.556817e+00
 8:    H   2.0  2.3   2.7   3.0      3.3       F2 2.806177e+01
 9:    I   3.7  4.0   4.3   4.7      5.0       F3 1.043644e+02
10:    J   5.3  5.7   6.0   6.3      6.7       F4 2.559003e+02
11:    K   6.7  7.0   7.3   7.7      8.0       F5 4.521117e+02
12:    L   8.3  8.7   9.0   9.3      9.7       F6 8.110778e+02
13:    M   0.1  0.2   0.3   0.4      0.6       F1 1.316698e-01

Upvotes: 0

Allan Cameron
Allan Cameron

Reputation: 174586

As long as you have all the functions defined, you can call them by name using do.call on a list of the arguments. You can therefore do this row-wise in your data frame, for example using sapply:

# Modify the original function slightly, as there is no variable called SPEED
F1 <- function(ALPHA,BETA,GAMMA,DELTA,CONSTANT){
  ((ALPHA * CONSTANT^ 2) + (BETA * 3) + GAMMA + (DELTA * log(CONSTANT))) 
}

# For the sake of the example, we will make F2 to F6 the same as F1
# But note these functions could all be different
F2 <- F3 <- F4 <- F5 <- F6 <- F1

df$answer <- sapply(seq(nrow(df)), 
                    function(i) do.call(df$FUNCTION[i], as.list(df[i, 2:6])))

df
#>    NAME ALPHA BETA GAMMA DELTA CONSTANT FUNCTION       answer
#> 1     A   1.0  2.0   3.0   4.0      5.0       F1 4.043775e+01
#> 2     B   6.0  7.0   8.0   9.0     10.0       F2 6.497233e+02
#> 3     C  11.0 12.0  13.0  14.0     15.0       F3 2.561913e+03
#> 4     D  16.0 17.0  18.0  19.0     20.0       F4 6.525919e+03
#> 5     E  20.0 21.0  22.0  23.0     24.0       F5 1.167810e+04
#> 6     F  25.0 26.0  27.0  28.0     29.0       F6 2.122428e+04
#> 7     G   0.3  0.7   1.0   1.3      1.7       F1 4.656817e+00
#> 8     H   2.0  2.3   2.7   3.0      3.3       F2 3.496177e+01
#> 9     I   3.7  4.0   4.3   4.7      5.0       F3 1.163644e+02
#> 10    J   5.3  5.7   6.0   6.3      6.7       F4 2.730003e+02
#> 11    K   6.7  7.0   7.3   7.7      8.0       F5 4.731117e+02
#> 12    L   8.3  8.7   9.0   9.3      9.7       F6 8.371778e+02
#> 13    M   0.1  0.2   0.3   0.4      0.6       F1 7.316698e-01

Created on 2022-02-04 by the reprex package (v2.0.1)


DATA USED

df <- structure(list(NAME = c("A", "B", "C", "D", "E", "F", "G", "H", 
"I", "J", "K", "L", "M"), ALPHA = c(1, 6, 11, 16, 20, 25, 0.3, 
2, 3.7, 5.3, 6.7, 8.3, 0.1), BETA = c(2, 7, 12, 17, 21, 26, 0.7, 
2.3, 4, 5.7, 7, 8.7, 0.2), GAMMA = c(3, 8, 13, 18, 22, 27, 1, 
2.7, 4.3, 6, 7.3, 9, 0.3), DELTA = c(4, 9, 14, 19, 23, 28, 1.3, 
3, 4.7, 6.3, 7.7, 9.3, 0.4), CONSTANT = c(5, 10, 15, 20, 24, 
29, 1.7, 3.3, 5, 6.7, 8, 9.7, 0.6), FUNCTION = c("F1", "F2", 
"F3", "F4", "F5", "F6", "F1", "F2", "F3", "F4", "F5", "F6", "F1"
)), class = "data.frame", row.names = c(NA, -13L))

Upvotes: 1

Related Questions