Home > Software engineering >  How to use a function inside a function in R?
How to use a function inside a function in R?

Time:11-19

I'm new to R and I'm trying to define a function in R where I call another function already in a R package (pgls and sma). I'm not sure how to do it or even if it is possible.

I have tried the following:

For pgls

getpgls <- function(P1, P2, dataf){
  PGLSt <- pgls(log(P1)~log(P2), data = dataf, lambda = 'ML')
}

When I call the function:

getpgls(sym('Long'), sym('massAvg'), CompData)

I get:

Error in log(P1) : non-numeric argument to mathematical function

Something similar happens with the sma function:

getsma <- function(P1, P2, dataf){
  SMAt <- sma(P1~P2, 
              log = "xy",
              data = dataf,
  )
}

when I call the function:

getsma(sym('Long'), sym('massAvg'), Data_Animal_de_pd)

I get the following error:

Error in model.frame.default(formula = P1 ~ P2, data = dataf, drop.unused.levels = TRUE) : 
object is not a matrix

When I run both pgls and sma with the same argumerts, but outside the function, it runs just fine. ie.

Long.SMA <- sma(Long~massAvg, 
                log = "xy",
                data = Data_Animal_de_pd, 
                )

and

Long.PGLS = pgls(log(Long)~log(massAvg), data = CompData, lambda = 'ML')

EDIT: Here I include small versions of CompData and Data_Animal_de_pd (only with 10 animals and the parameters massAvg and Long).

The class of CompData is "comparative.data" and comes from a function comparative.data which connects a phylogenetic tree with another data frame (Data_Animal_de_pd).

> dput(CompData)
structure(list(phy = structure(list(edge = structure(c(11L, 12L, 
13L, 14L, 14L, 15L, 15L, 16L, 17L, 17L, 16L, 13L, 12L, 18L, 18L, 
11L, 19L, 19L, 12L, 13L, 14L, 1L, 15L, 2L, 16L, 17L, 3L, 4L, 
5L, 6L, 18L, 7L, 8L, 19L, 9L, 10L), dim = c(18L, 2L)), edge.length = c(100.597661, 
5.254328, 4.311278, 71.0845800943, 34.327960646, 36.7566030561, 
5.779375747, 15.0619109945, 15.9153248095, 15.9153245794, 30.9772360366, 
75.39586827, 44.21113726, 36.439042146, 36.4390420969, 108.977279909, 
72.27059073, 72.270578302), Nnode = 9L, tip.label = c("Tupaia_minor", 
"Hystrix_cristata", "Geocapromys_brownii", "Myocastor_coypus", 
"Hydrochoerus_hydrochaeris", "Rhinoceros_sondaicus", "Dasypus_hybridus", 
"Tolypeutes_matacus", "Caluromysiops_irrupta", "Acrobates_pygmaeus"
), node.label = 11:19), class = "phylo", order = "cladewise"), 
    data = structure(list(massAvg = c(0.045, 20, 1.5, 7.5, 50.5, 
    1350, 5.5, 1.5, 0.45, 0.01), Long = c(21.565, 110.4, 55.52, 
    68.3266666666667, 175.2, 447.4, 47.02, 44.68, 38.58, 12.67
    )), row.names = c("Tupaia_minor", "Hystrix_cristata", "Geocapromys_brownii", 
    "Myocastor_coypus", "Hydrochoerus_hydrochaeris", "Rhinoceros_sondaicus", 
    "Dasypus_hybridus", "Tolypeutes_matacus", "Caluromysiops_irrupta", 
    "Acrobates_pygmaeus"), class = "data.frame"), data.name = "datanm2[, c(\"massAvg\", \"Long\", \"Sci_name2\")]", 
    phy.name = "newphy", dropped = list(tips = character(0), 
        unmatched.rows = character(0))), class = "comparative.data")

Data_Animal_de_pd is a data frame that contains the information of the animals such as the length of the bones, etc.

> dput(Data_Animal_de_pd)
structure(list(massAvg = c(20, 50.5, 7.5, 1350, 0.45, 0.045, 
1.5, 5.5, 1.5, 0.01), Long = c(110.4, 175.2, 68.3266666666667, 
447.4, 38.58, 21.565, 55.52, 47.02, 44.68, 12.67), Sci_name = c("Hystrix cristata", 
"Hydrochoerus hydrochaeris", "Myocastor coypus", "Rhinoceros sondaicus", 
"Caluromysiops irrupta", "Tupaia minor", "Geocapromys brownii", 
"Dasypus hybridus", "Tolypeutes matacus", "Acrobates pygmaeus"
), Sci_name2 = c("Hystrix_cristata", "Hydrochoerus_hydrochaeris", 
"Myocastor_coypus", "Rhinoceros_sondaicus", "Caluromysiops_irrupta", 
"Tupaia_minor", "Geocapromys_brownii", "Dasypus_hybridus", "Tolypeutes_matacus", 
"Acrobates_pygmaeus")), row.names = c("10137", "10149", "10157", 
"102233", "126286", "143289", "1543402", "1756220", "183749", 
"190720"), class = "data.frame")```

CodePudding user response:

To make your function work with symbols (i assume from rlang::sym) you must inject them with rlang::inject:

getsma <- function(P1, P2, dataf){
  SMAt <- rlang::inject(sma(!!P1 ~ !!P2, 
              log = "xy",
              data = dataf,
  ))
}

but you can instead substitute and inject arguments:


getsma <- function(P1, P2, dataf){
  P1 <- rlang::enexpr(P1)
  P2 <- rlang::enexpr(P2)
  SMAt <- rlang::inject(sma(!!P1 ~ !!P2, 
              log = "xy",
              data = dataf,
  ))
}

Then call them directly:

getsma(Long, massAvg, Data_Animal_de_pd)
  • Related