Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

This sample logic is going to query PA data, and run a linear regression on it in R. To expose the regression as a Calculation Step in the Optimization module, we need to define the calculationStepsEntry. Here we define just one step: Regression.Image Removed

...

This materialized in the Optimization UI as a tab in Step 2. We will not define any inputs to the model, and will have a look at the Results further down. Calculating the model (top-left Calculate button) results in the elements with Calculation Context = 'Calculation' to be executed. The results then show up in the Results pane on the right, but you will need to click the Refresh button in the top button bar first.Image Removed

...

Now we can focus on the actual logic. We have defined a generic lm() function in the Lib element, acting as a gateway to the real lm() function in R. We are getting the PA data, and calling the lm() function, passing in the linear model formula and data, in the Regression element. The Fit element only serves to show the familiar output in R. Here is some sample code:

Lib
paste-
paste-code-macro
title
languagegroovyLib
def lm(r, formula, factors, data) {
  script = """
  			summary <- summary(fit)
  			coeffs <- summary\$coefficients[,1]
  			stderrs <- summary\$coefficients[,2]
  			pvalues <- summary\$coefficients[,4]
  			r2 <- summary\$r.squared
			"""
  r.assign("data", data)
  if (factors) {
    factors.forEach{ name, values ->
      def levels = values.collect{ "\"$it\"" }.join(",")
      r.eval("data <- transform(data, $name = factor($name, levels = c($levels)))" as String)
    }
  }
  r.eval("fit <- lm($formula, data)" as String)
  r.eval(script)

  def rcoeffs = r.get("coeffs")
  def rparams = rcoeffs.getAttribute("names")
  // in the case that we only get an Intercept (i.e. avg of one of the regression params
  // (due to lack of variation in the data), then for some reason we are not getting
  // any names back.
  def params = rparams? rparams.asStrings() as List : ["(Intercept)"]
      
  def coeffs = rcoeffs.asDoubles()
  def stderrs = r.get("stderrs").asDoubles()
  def pvalues = r.get("pvalues").asDoubles()
  def r2 = r.get("r2").asDouble()

  api.logInfo("lm.result", r.print("summary"))
  api.logInfo("lm.params", params)  
  api.logInfo("lm.coeffs", coeffs.toString())
  api.logInfo("lm.stderrs", stderrs.toString())
  api.logInfo("lm.pvalues", pvalues.toString())
  api.logInfo("lm.R2", r2)
  
  return [ params: params, coeffs: coeffs, stderrs: stderrs, pvalues: pvalues, R2:r2 ]
}
Regression
Code Block
languagegroovytitleRegression
if (api.isSyntaxCheck()) return


def r = model.getRContext()
def dmCtx = api.getDatamartContext()
def dm = dmCtx.getDatamart("Transaction DM")

def query = dmCtx.newQuery(dm, false)
query.select("brand_name", "brand")
query.select("proprietary_brand_flag", "proprietary")
query.select("footwear_order_flag", "footwear")
query.select("hardgood_order_flag", "hardgood")
query.select("margin_percent", "margin")

def data = dmCtx.executeQuery(query)?.data

r.assign("data", data)
def result = Lib.lm(r, "margin ~ brand + proprietary + footwear + hardgood", null, data)
def fit = r.print("fit")

api.local.fit = fit
return result

The Fit element then merely returns api.local.fit, resulting in the following (regression parameters, coefficients etc. are shown in expandable tree nodes):

Image Removed

...

Finally, a link to the tiny R-API:  https://qa.pricefx.eu/pricefx-api/groovy/master/net/pricefx/formulaengine/scripting/RContext.html