YAML: Define an R function

Datetime:2016-08-23 01:43:51          Topic: R Program           Share

(This article was first published on R – ipub , and kindly contributed toR-bloggers)

YAML to define hierarchic models

Glenn is using the data.tree package to model commercial mortgage-backed securities. If you don’t know what that is, you can read it all up on Wikipedia . But in a nutshell, CMBS (or REMIC) are financial instruments that bundle multiple commercial real estate mortgages, and securitize (or bundle) them into tradeable entities. A CMBS has multiple tranches, and multiple classes of tranches. Each tranche starts paying interest depending on certain conditions.

Glenn knows much more about this than me, of course. He wrote a great book about the topic, and also published an R package that accompanies the book. More recently, he started to realize that MBS structures are in essence tree structures. And if you start modelling MBS as trees, many of the complexities start disappearing. So he started to rewrite the bond lab package, using data.tree. I hope he’ll find time to publish a guest post here as soon as that is published!

YAML and data.tree

Anyway, one thing he’d like to do is to define the MBS structure in a YAML files. This is straight forward. I’ve shown how to do this, for example, in the AHP package, or in the decision tree example in the data.tree applications vignette. In a nutshell, you define your tree structure in a file, and load it using the R yaml package. The resulting list-of-list you then convert to a data.tree structure:

library(data.tree)
library(yaml)


yaml <- "
node1:
  value: 2
node2:
  value: 6
"


lol <- yaml.load(yaml)
tree <- as.Node(lol)

YAML and functions

Now, Glenn asked me whether it’s possible to define R functions in the YAML file.

Answer: Yes!

All you need is an additional step to parse and evaluate the functions, so as to convert them from strings to actual R functions.

yaml <- "
node1:
 value: 2
 fnct: >
 function(x) {
 2 * x
 }
node2:
 value: 6
 # can be named if you prefer, though that will have no impact
 fnct: >
 DoCalculate <- function(node) {
 node$value * 2
 }
"

lol <- yaml.load(yaml)
tree <- as.Node(lol)

evaluator <- function(node) node$fnct <- eval(parse(text = node$fnct))

tree$Do(fun = evaluator, 
 filterFun = function(node) !is.null(node$fnct))

tree$node1$fnct(5)
tree$node2$fnct(tree$node2)

This will call the function, as expected. For example, this technique has been used for the ahp package, where we can define preference functions in our ahp yaml model.

Functions that reference a node

Obviously, it doesn’t end here. What we would like to do, very often, is to reference the enclosing data.tree from a given function. This is also possible. All we need to do is to wrap the function, like so:

# if you want to reference an enclosing node from within your function, you can define the functions
# having a node argument, and do a slightly more complex evaluator function. e.g.

yaml <- "
node1:
  value: 2
  fnct: >
    function(node) {
      2 * node$value
    }
node2:
  value: 5
  fnct: >
    function(node) {
      node$value ^ 2 
    }

"


lol <- yaml.load(yaml)
tree <- as.Node(lol)

evaluator <- function(node) {
  f <- eval(parse(text = node$fnct))
  # warp the function and call using node
  f2 <- function() {
    f(node)
  }
  node$fnct <- f2
}


tree$Do(fun = evaluator, 
        filterFun = function(node) !is.null(node$fnct))



tree$node1$fnct()
tree$node2$fnct()


Aggregate(tree, "fnct", sum)

I hope you find this useful!

You can download the entire code from this gist .

The post YAML: Define an R function appeared first on ipub .





About List