Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
calculate_r_expression [2026/07/19 21:35]
hermann
calculate_r_expression [2026/07/22 18:13] (current)
hermann
Line 3: Line 3:
 ===== Description ===== ===== Description =====
  
-This is a **[[ego_script#​container_functors|container functor]]** that calls R externally ​and processes ​the script'​s outputs as if they were part of Dinamica EGO itself. Like the other calculator functors, data is connected through hook functors placed inside its ''<​nowiki>​{{ … }}</​nowiki>''​ block.+This is a **[[ego_script#​container_functors|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 ''<​nowiki>​{{ … }}</​nowiki>''​ block.
  
 ===== Inputs ===== ===== Inputs =====
Line 24: Line 24:
 ==== Expression inputs ==== ==== Expression inputs ====
  
-Data is passed into the expression through **hook** functors placed inside the container'​s ''<​nowiki>​{{ … }}</​nowiki>''​ block. Hooks can be added using the //Create a hook// button on the functor bar, or by dragging them in individually.+Data is passed into the expression through **hook** functors placed inside the container'​s ''<​nowiki>​{{ … }}</​nowiki>''​ block — the same [[ego_script#​verbose_form|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''​   * Tables and lookup tables → [[Number Table]] → available in R as ''​t1'',​ ''​t2'',​ …, ''​t100''​
Line 40: Line 40:
 <code rsplus> <code rsplus>
 # Access the third key and its corresponding value in lookup table t1 # Access the third key and its corresponding value in lookup table t1
-patchId ​  ​<- t1$Key[ 3 ]; +patchId <- t1$Key[3];​ 
-patchArea <- t1$Value[ 3 ];+patchArea <- t1$Value[3];​
 </​code>​ </​code>​
  
 A **table** is transferred as a [[https://​en.wikibooks.org/​wiki/​R_Programming/​Working_with_data_frames|DataFrame]],​ with each column likewise accessed using ''​$''​. Two conventions apply to tables in either direction: A **table** is transferred as a [[https://​en.wikibooks.org/​wiki/​R_Programming/​Working_with_data_frames|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 [[calculate_functors#​connecting_data_inputs|Connecting Data Inputs]]). +  * **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 [[calculate_functors#​connecting_data_inputs|Connecting Data Inputs]]). A key column can be Real or String, the same as any other column
-  * 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.+  * Each column'​s type is inferred from its data, the same rule that applies to any table (see [[ego_script#​constants|Constants]]):​ a numeric vector produces a Real column, a character vector produces a String column. ​R automatically converts string columns to **Factors** inside a ''​data.frame'', ​and a Factor is neither of those — Dinamica requires plain **Character Vectors** ​to infer String correctly. Always build tables with ''​stringsAsFactors = FALSE''​ to prevent this conversion.
  
 For further detail on the underlying table representation,​ see [[external_communication#​table|External Communication]]. For further detail on the underlying table representation,​ see [[external_communication#​table|External Communication]].
Line 53: Line 53:
 ==== Expression outputs ==== ==== 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:+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 ^ Example ^ +^ Function ^ Output type ^ Notes ^ Example ^ 
-| ''​outputDouble()''​ | Real | ''​outputDouble("​myDouble",​ 3.14)''​ | +| ''​outputDouble()''​ | Real | Accepts any numeric value. ​| ''​outputDouble("​myDouble",​ 3.14)''​ | 
-| ''​outputNumberVector()''​ | Tuple | ''​outputNumberVector("​myTuple",​ c(1:​10))''​ | +| ''​outputNumberVector()''​ | Tuple | Accepts any collection of numbers. ​| ''​outputNumberVector("​myTuple",​ c(1:​10))''​ | 
-| ''​outputString()''​ | String | ''​outputString("​myString",​ "This is a string"​)''​ | +| ''​outputString()''​ | String ​| Accepts any string value. ​| ''​outputString("​myString",​ "This is a string"​)''​ | 
-| ''​outputLookupTable()''​ | Lookup Table | ''​outputLookupTable("​myLUT",​ c(1:10), c(1:10) * 10)''​ | +| ''​outputLookupTable()''​ | [[Lookup Table Type|Lookup Table]] | Requires two number vectors of equal length — one for the keys, one for the values. Lookup tables are always Real-typed on both sides; there is no String option. ​| ''​outputLookupTable("​myLUT",​ c(1:10), c(1:10) * 10)''​ | 
-| ''​outputTable()''​ | Table | ''​outputTable("​myTable",​ data.frame(State = c("​Massachusetts",​ "​Massachusetts"​),​ City = c("​Boston",​ "​Chelsea"​),​ Population = c(667137, 39398), stringsAsFactors = FALSE), 2)''​ | +| ''​outputTable()''​ | Table | Requires ​a table built with the [[https://​www.r-tutor.com/​r-introduction/​data-frame|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)''​ |
- +
-Values passed to these functions can be constructed inline, as in the examples above, or supplied as variables. +
- +
-  * Any numeric value can be passed to ''​outputDouble()''​. +
-  * Collections of numbers are valid number vectors for ''​outputNumberVector()''​. +
-  * A [[Lookup Table Type|lookup table]] requires two number vectors of equal length — one for the keys, one for the values. +
-  * ''​outputTable()''​ requires ​a table built with the [[http://​www.r-tutor.com/​r-introduction/​data-frame|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.+
  
 ==== Retrieving outputs ==== ==== Retrieving outputs ====
Line 81: Line 74:
  
 Each functor takes two inputs: the ''​Struct''​ returned by ''​CalculateRExpression'',​ and the name of the entry to extract as a string constant. 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|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.
 +
 +<code rsplus>
 +dinamicaPackage("​moments"​);​
 +</​code>​
  
 ==== Setup ==== ==== Setup ====
  
-There are two ways to run R scripts from ''​CalculateRExpression''​.+There are two ways to run R scripts from ''​CalculateRExpression'' ​— though only the local installation is available on Linux.
  
 === Dinamica EGO Enhancement Plugin === === Dinamica EGO Enhancement Plugin ===
  
-Download and install the [[plugins_4|Dinamica EGO Enhancement Plugin]]. It contains everything needed to run R scripts inside Dinamica EGO, with no further configuration.+Windows only. Download and install the [[plugins_4|Dinamica EGO Enhancement Plugin]]. It contains everything needed to run R scripts inside Dinamica EGO, with no further configuration.
  
 === Local R installation === === Local R installation ===
  
-Alternativelya local R installation can be used insteadThis requires:+On Linuxthis 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 pluginEither way, it requires:
  
-  * R version 3.3.1 or later. +  * R installed on the machine, with the ''​Rscript''​ executable (''​Rscript.exe'' ​on Windows) present ​in its ''​bin''​ sub-folder.
-  * A valid ''​Rscript.exe'' ​located ​in the R installation'​s ​''​bin''​ sub-folder.+
   * The [[external_communication|Dinamica package]] for R installed and at its latest version.   * The [[external_communication|Dinamica package]] for R installed and at its latest version.
  
-To use a custom R installationgo to //Tools// → //Options// → //​Integration//​ tab and enable ​//Use alternative R installation for Calculate R Expression//​+On Windowsthis alternative installation is selected in the Dinamica EGO GUI by going to //Tools// → //Options// → //​Integration//​ tab and enabling ​//Use alternative R installation for Calculate R Expression//​.
- +
-{{:​dinamica_options_use_alternative_r_install.png?​nolink|}}+
  
 ==== Examples ==== ==== Examples ====
Line 113: Line 113:
  
 <code rsplus> <code rsplus>
-patchMean <- mean( t1$Value ); +patchMean <- mean(t1$Value);​ 
-patchTotal <- sum( t1$Value ); +patchTotal <- sum(t1$Value);​ 
-print( paste( "​Processed",​ length( t1$Value ), "​patches"​ ) );+print(paste("​Processed",​ length(t1$Value),​ "​patches"​));​
  
-outputDouble( "​meanArea",​ patchMean ); +outputDouble("​meanArea",​ patchMean);​ 
-outputDouble( "​totalArea",​ patchTotal );+outputDouble("​totalArea",​ patchTotal);​
 </​code>​ </​code>​
  
Line 127: Line 127:
 <code rsplus> <code rsplus>
 aboveThreshold <- t1$Value >= v1; aboveThreshold <- t1$Value >= v1;
-filteredKeys <- t1$Key[ aboveThreshold ]; +filteredKeys <- t1$Key[aboveThreshold];​ 
-filteredValues <- t1$Value[ aboveThreshold ];+filteredValues <- t1$Value[aboveThreshold];​
  
-outputLookupTable( "​filteredPatches",​ filteredKeys,​ filteredValues );+outputLookupTable("​filteredPatches",​ filteredKeys,​ filteredValues);​
 </​code>​ </​code>​
  
Line 142: Line 142:
     stringsAsFactors = FALSE     stringsAsFactors = FALSE
 ); );
-names( patchFlags )[ 3 ] <- s1;+names(patchFlags)[3] <- s1;
  
-outputTable( "​patchSummary",​ patchFlags, 1 );+outputTable("​patchSummary",​ patchFlags, 1); 
 +</​code>​ 
 + 
 +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: 
 + 
 +<code rsplus>​ 
 +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);
 </​code>​ </​code>​
  
 ==== Writing the expression in EGO Script ==== ==== Writing the expression in EGO Script ====
  
-Like [[Calculate Python Expression]],​ the ''​Expression''​ input is type [[ego_script#​constants|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 [[ego_script#​inline_syntax|inlined]] directly into the call.+Like [[calculate_python_expression|Calculate Python Expression]],​ the ''​Expression''​ input is type [[ego_script#​constants|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 [[ego_script#​inline_syntax|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. 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.
Line 156: Line 178:
 result := CalculateRExpression (String $"( result := CalculateRExpression (String $"(
 aboveThreshold <- t1$Value >= v1; aboveThreshold <- t1$Value >= v1;
-outputLookupTable( "​filteredPatches",​ t1$Key[ aboveThreshold ], t1$Value[ aboveThreshold ] );+outputLookupTable("​filteredPatches",​ t1$Key[aboveThreshold],​ t1$Value[aboveThreshold]);​
 )") .no {{ )") .no {{
     NumberTable landCoverAreas 1;     NumberTable landCoverAreas 1;
Line 171: Line 193:
  
 CalculateRExpression CalculateRExpression
- 
-===== See Also ===== 
- 
-  * [[r_coupling|R Coupling]] 
-  * [[Calculate Python Expression]] 
-  * [[External Communication]] 
-  * [[ego_script#​container_functors|EGO Script — Container Functors]] 
-  * [[ego_script#​verbose_form|EGO Script — Verbose Form (Hooks)]] 
-  * [[calculate_functors|Calculate Functors — Complete Operator Documentation]] 
- 
-