Table Splicing
Overview of Table Splicing
"Table splicing" refers to what happens to the contents of a input table (including Edit Tables, Subtable, DetermTable, or ProbTable) when you add, delete, or reorder elements of an index of the table. It is especially important when a table index is computed (rather than an explicit list), so that it may change automatically as a function of its inputs. Analytica is pretty smart about handling these changes -- and offers options to let you modify the default behavior. These features are also in ADE.
When a computed index changes, there may be correspondence ambiguity -- i.e., there may be an inherent ambiguity in how the previous values map to the new values. This impacts how tables are spliced, and how much data gets lost. You can specify whether an index should be positionally corresponded, associationally corresponded, or flexibly corresponded.
The SubTable function allows you to display a portion of a table as if it were its own edit table, but where changes to the SubTable actually cause the values in the main table to be changed. The slices (rows/cols) of the subtable may even re-ordered, and the values may appear in input controls on a diagram.
When new slices are added to an index, so that new cells are added to tables based on that index, you can control what values the new cells receive. It is even possible to specify a different cell default for each column (and these may include choice pulldowns). One option are blank cells (no contents), such that the new table cells have nothing in them. Blank cells receive some special treatment.
Finally, if you need to minimize the time to reload a model from file, you can take advantage of commands that force tables to be spliced immediately. Doing this prior to saving your model means splicing will not have to occur when the user of your model accesses or evaluates the tables. For these, see SpliceIndex and SpliceTable.
Tables Based on Computed Indexes
Most commonly, each index of an Edit Table is defined as an explicit list of numbers or labels. You can easily edit, add, or remove items in such a list explicitly, using standard methods on the index or in an Edit table that uses that index.
Sometimes, you may want to use an index that is computed -- that is generated as the result of evaluating an expression: A common case is an index computed using Concat of two other indexes. Another is computing an index using the Subset function. In the latter case, it is usually better to use SubTable. In the case of a DetermTable and ProbTable, you can also set the variable's Domain attribute to an index (an index domain), which may be computed.
Default Values
Default cell values for tables can be specified; however, the mechanisms for controlling defaults are not exposed through the Analytica Graphical User Interface (GUI), and must be set up through typescript. Currently, these mechanisms are somewhat "fragile", in that they may not handle error conditions gracefully, which is also part of the reason it is not yet exposed more prominently.
Sys_TableCellDefault
The system variable Sys_TableCellDefault contains the scalar default used to populate new table cells when rows/columns/slices are added or inserted into a table. The system variable contains a text value, which is inserted verbatim, and thus should be a valid expression.
Currently this system variable can only be changed using the typescript window. To do this, access the typescript window by pressing Cntl+' (Control+apostrophe).
Any of the following typescript commands can be used to change the default cell value, for example to 0, blank (empty), or Null:
Sys_TableCellDefault: 0
Sys_TableCellDefault:
Sys_TableCellDefault: Null
Blank (empty) Default Cells
You can use empty cells to indicate that the table cell hasn't yet been filled in. If you attempt to evaluate a table containing empty cells, a warning is issued. The warning is helpful in identifying table cells that still need to be filled in.
When you change an index, for example, adding new values, Analytica will automatically propagate the changes through your model. However, you also need to remember to fill in new cells in tables based on that index. Using the blank default helps prevent bad results should you forget to fill in a table. Rather than just assuming the value is zero, a blank value causes a warning, and if you ignore the warning, the empty cells evaluate to Null, which will generally propagate through your model and make it obvious that values are missing.
Although not yet available as a feature, in the future tables with blank cells will also be listed on the "Show Invalid Variables" dialog.
When blank cells are present, the textual table definition will contain commas with nothing between them. For example:
Table(I)(1,,,, 4,,, 5,)
This table definition has three cells with values and six empty cells.
Suppressing Empty Cell Warnings
Sysvar Sys_WarnUndefCell
Suppression or activation of the empty cell warning is controlled by system variable Sys_WarnUndefCell. If this is true, a warning is issued when a table containing empty cells is evaluated. Setting this to zero (false) deactivates this warning. This warning can be suppressed without deactivating warnings in general.
This preference is currently not available from the Analytica GUI, and thus can only be set via typescript. To access typescript, press Ctrl+' . To activate empty cell warnings, type:
Sys_WarnUndefCell: 1
To suppress these warnings, type:
Sys_WarnUndefCell: 0
When warnings are suppressed, empty cells evaluate to Null.
Table-Specific Default
Cell Default
An individual table may also contain its own default value, which overrides the global cell default. Also, unlike the global default, the table-specific default can specify a different value for each column. For example, if you want one column to always contain a particular Choice pulldown, this can be specified.
The Cell Default attribute specifies the scalar default used to populate new table cells when rows/columns/slices are added or inserted into a table (the Attribute identifier is TableCellDefault
). To change this, you first need to enable the Cell Default attribute to be visible in the Attribute pane and Object Window by going to the Attributes dialog on the Object menu and putting a checkmark next to Cell Default. Then, select Cell Default in the attribute pane.
To specify the same default for every cell that is added to the table, either specify a number, Null, or a quoted string. If you specify a quoted string, the contents of the string should either be empty (an empty cell) or a valid expression (where the outer quotes are not included as part of the expression). For example, the following Cell Default values ase useful defaults for all cells in a table:
0
{ Use numeric zero as default }''
{ Use empty cell as default }Null
{ "Use Null as the default }"'n/a'"
{ Use the quoted text 'n/a' as the default }
If you change these from typescript, or from a button script (less common), you would use:
TableCellDefault A: 0 { Use numeric zero as default }
TableCellDefault A: "" { Use empty cell as default }
TableCellDefault A: Null { Use Null as the default }
TableCellDefault A: "'n/a'" { Use the quoted string 'n/a' as the default }
You should not specify defaults that are syntactically invalid. For example, do not use:
TableCellDefault A: '<<fill in>>'
For more complex defaults, such as table where each column gets a different default expression, you should set up a separate edit table to hold the defaults, and then specify its identifier in the Cell Default attribute. For example:
Index Columns := ['a', 'b', 'c']
Variable A_default := Table(Columns)(0, Choice(Regions, 1),)
TableCellDefault A := A_default
{ EnterA_default
in the Cell Defaults }definition A := Table(Rows, Columns)
In this example, A_default is
an edit table containing 0 in the first column, a choice pulldown in the second column, and an empty cell in the final column. These are the column defaults for the edit table in A
. When an element is added to the Row index, so that a row is added to the table A
, the values in the edit table for A_default
are used, with the first column defaulting to 0, the second to a choice pulldown, and the third column to an empty cell.
Correspondence methods for splicing
Attribute CorrespondenceMethod
When a computed index changes -- index values are changed, added, reordered -- each Edit table using that index must change to reflect those changes. In some, cases it may delete or reorder slices from the old Edit table. There are three Correspondence methods to determine how it does that:
- Positional correspondence
- It retains correspondence by position along the index, so that the first slice (row, column, or subarray) of the table over the changing index is still the first; the second remains the second; and so on -- even if values or labels of the Index change. For example, if you change the 3rd element of index
Fuel_types
from"Gasoline"
to"Petrol"
, it won't affect the values. If the index becomes smaller, it deletes the excess slices at the end. If it becomes larger, it creates new new slices with the default values.
- Associational correspondence
- Any index element whose value stays the same retains the same slice values. For example, if the index
Fuel_types
contains the element"Gasoline"
as its third element, if you insert additionalFuel_type "Ethanol
before it, moving"Gasoline"
to become the fourth element -- it will retain the same slice under the label value as"Gasoline"
. Any insertion, deletion, or reordering of values in the Index will retain the slice values for values (labels) that are the same. Deleting a value from the index will delete the corresponding slice. Adding an element will create a new slice with default values. Renaming an element will delete the original slice, replacing it by a slice with default values.
- Flexible correspondence
- This is the default method, and is a combination of positional and associational correspondence. If the index values remain the same, but are reordered, it preserves associational correspondence. If it finds new index values that didn't exist in the old index, for example changing
"Gasoline"
to"Petrol"
, it tries to match them positionally, and retains the old data.
You can control the correspondence method using the CorrespondenceMethod attribute.
<tip title="Important" The correspondence method is an attribute of the index, not of individual tables that use it. All tables based on a given index will be treated identically. </tip>
The CorrespondenceMethod attribute is not reflected by the Analytica GUI. Changes to the default correspondence method must be done through typescript (press Ctrl+' to access the Typescript window). You can alter the settings as follows:
CorrespondenceMethod I: 0 { Default method }
CorrespondenceMethod I: 1 { Positional Correspondence }
CorrespondenceMethod I: 2 { Associational Correspondence }
CorrespondenceMethod I: 3 { Flex correspondence }
Enable comment auto-refresher