Calculate R Expression

Description

This is a container functor that calls R externally with the user-defined expression. Like the other calculator functors, data is connected through hook functors placed inside its {{ … }} block.

Inputs

Name Type Description
Expression Code The expression that will run on R. Code values cannot be written as plain text constants in EGO Script — see Writing the expression in EGO Script below.
Treat Warning As Errors Boolean Value Type Warnings raised by the R script will be treated as errors.

Optional Inputs

None.

Outputs

Name Type Description
result Struct A struct containing the output values generated by the expression.

Notes

Expression inputs

Data is passed into the expression through hook functors placed inside the container's {{ … }} block — the same verbose form hook mechanism used by the calculator functors. Hooks can be added using the Create a hook button on the functor bar, or by dragging them in individually.

  • Tables and lookup tables → Number Table → available in R as t1, t2, …, t100
  • Scalar values → Number Value → available as v1, v2, …, v100
  • Strings → Number String → available as s1, s2, …, s100

Maps cannot be connected — this functor has no cell context. There is no shorthand notation; see Calculate Functors — Complete Operator Documentation for the general hook mechanism and syntax.

Tables and lookup tables

Lookup tables and tables require extra care, since each is transferred to R using a different representation.

A lookup table is transferred as a list with two columns, Key and Value. Each column is accessed with the $ operator:

# Access the third key and its corresponding value in lookup table t1
patchId <- t1$Key[3];
patchArea <- t1$Value[3];

A table is transferred as a DataFrame, with each column likewise accessed using $. Two conventions apply to tables in either direction:

  • Key columns are marked by an asterisk (*) appended to their column name — this is the same convention used throughout Dinamica EGO's table representation (see Connecting Data Inputs).
  • R automatically converts string columns to Factors inside a data.frame, but Dinamica requires plain Character Vectors. Always build tables with stringsAsFactors = FALSE to prevent this conversion.

For further detail on the underlying table representation, see External Communication.

Expression outputs

Values are returned to Dinamica by calling one of the following functions from the R script. Every call requires an identifier as its first parameter — the name Dinamica uses to place the value into the output struct — and the value itself, which can be constructed inline, as in the examples below, or supplied as a variable:

Function Output type Notes Example
outputDouble() Real Accepts any numeric value. outputDouble(“myDouble”, 3.14)
outputNumberVector() Tuple Accepts any collection of numbers. outputNumberVector(“myTuple”, c(1:10))
outputString() String Accepts any string value. outputString(“myString”, “This is a string”)
outputLookupTable() Lookup Table Requires two number vectors of equal length — one for the keys, one for the values. outputLookupTable(“myLUT”, c(1:10), c(1:10) * 10)
outputTable() Table Requires a table built with the data.frame function, using stringsAsFactors = FALSE as described above. Its optional second parameter (default 1) sets how many leading columns, from the left, are key columns. outputTable(“myTable”, data.frame(State = c(“Massachusetts”, “Massachusetts”), City = c(“Boston”, “Chelsea”), Population = c(667137, 39398), stringsAsFactors = FALSE), 2)

Retrieving outputs

CalculateRExpression returns a single Struct value (via its result output port) containing every value passed to an output*() function. To retrieve individual values from that struct, use the corresponding functor from the Integration group:

Functor Retrieves
Extract Struct Number A value passed to outputDouble()
Extract Struct Tuple A value passed to outputNumberVector()
Extract Struct String A value passed to outputString()
Extract Struct Lookup Table A value passed to outputLookupTable()
Extract Struct Table A value passed to outputTable()

Each functor takes two inputs: the Struct returned by CalculateRExpression, and the name of the entry to extract as a string constant.

Installing packages

Packages are installed by calling dinamicaPackage(“packageName”) from within the expression — one call per package. Unlike Calculate Python Expression, there is no separate input port for listing packages; dinamicaPackage() is the only mechanism available.

dinamicaPackage(“packageName”) also acts as R's library() call: when the package name matches the name of the module to load, calling it both installs the package (if not already present) and loads it, in a single call.

dinamicaPackage("moments");

Setup

There are two ways to run R scripts from CalculateRExpression — though only the local installation is available on Linux.

Dinamica EGO Enhancement Plugin

Windows only. Download and install the Dinamica EGO Enhancement Plugin. It contains everything needed to run R scripts inside Dinamica EGO, with no further configuration.

Local R installation

On Linux, this is the only option — Dinamica EGO always uses the R installation already present on the system. On Windows, it can be used as an alternative to the plugin. Either way, it requires:

  • R installed on the machine, with the Rscript executable (Rscript.exe on Windows) present in its bin sub-folder.
  • The Dinamica package for R installed and at its latest version.

On Windows, this alternative installation is selected in the Dinamica EGO GUI by going to ToolsOptionsIntegration tab and enabling Use alternative R installation for Calculate R Expression.

Examples

The following examples use a consistent set of inputs:

  • t1 — a lookup table of land cover patches, mapping Key (patch identifier) to Value (patch area)
  • v1 — a scalar minimum area threshold
  • s1 — a string giving the name to use for the threshold flag column

Compute the mean and total area across all patches, and report progress to the Message Log:

patchMean <- mean(t1$Value);
patchTotal <- sum(t1$Value);
print(paste("Processed", length(t1$Value), "patches"));
 
outputDouble("meanArea", patchMean);
outputDouble("totalArea", patchTotal);
Note: The print() call is visible in Dinamica EGO's Message Log, shown as a Result-level message. Log levels are ordered Unconditional, Error, Warning, Result, Info, Info2, Debug, Debug2 — messages printed from R are only shown when the Message Log level is set to Result or a more verbose level; at Unconditional, Error, or Warning they are suppressed.

Filter the lookup table down to patches whose area meets the threshold, and return the filtered lookup table:

aboveThreshold <- t1$Value >= v1;
filteredKeys <- t1$Key[aboveThreshold];
filteredValues <- t1$Value[aboveThreshold];
 
outputLookupTable("filteredPatches", filteredKeys, filteredValues);

Build and return a table with one row per patch, including a column that flags whether each patch meets the threshold. The column's name is taken from the passed string s1 rather than being hard-coded:

patchFlags <- data.frame(
    PatchId = t1$Key,
    Area = t1$Value,
    MeetsThreshold = t1$Value >= v1,
    stringsAsFactors = FALSE
);
names(patchFlags)[3] <- s1;
 
outputTable("patchSummary", patchFlags, 1);

Install the moments package and use it to compute the skewness of the patch area distribution — a statistic not available in base R — then flag patches whose area is a statistical outlier:

dinamicaPackage("moments");
 
patchMean <- mean(t1$Value);
patchStdDev <- sd(t1$Value);
patchSkewness <- skewness(t1$Value);
 
isOutlier <- abs(t1$Value - patchMean) > 2 * patchStdDev;
outlierPatches <- data.frame(
    PatchId = t1$Key[isOutlier],
    Area = t1$Value[isOutlier],
    stringsAsFactors = FALSE
);
 
outputDouble("meanArea", patchMean);
outputDouble("stdDevArea", patchStdDev);
outputDouble("skewnessArea", patchSkewness);
outputTable("outlierPatches", outlierPatches, 1);

Writing the expression in EGO Script

Like Calculate Python Expression, the Expression input is type Code, which is represented in the underlying script using base64 encoding — impractical to write or edit directly as a text constant. Instead, connect a String carrier functor containing the R expression text to the Expression port; its output is accepted wherever a Code value is expected. Since only this one output is needed, the carrier can be inlined directly into the call.

This limitation is specific to hand-written EGO Script. In the Dinamica EGO GUI, the Expression port has a dedicated code editor that edits the Code value directly — the String carrier workaround is only necessary when writing or editing the .ego file as text.

result := CalculateRExpression (String $"(
aboveThreshold <- t1$Value >= v1;
outputLookupTable("filteredPatches", t1$Key[aboveThreshold], t1$Value[aboveThreshold]);
)") .no {{
    NumberTable landCoverAreas 1;
    NumberValue minimumArea    1;
}};
filteredPatches := ExtractStructLookupTable result "filteredPatches";

Group

Internal Name

CalculateRExpression