Difference between revisions of "Excel to Analytica Mappings/Lookup Functions"

(VLookup - screenshot example)
 
(6 intermediate revisions by 2 users not shown)
Line 11: Line 11:
  
 
In an Analytica model, if you want to store the "address" of a datum in an array, you would record the index values that specify its coordinates.  To some extent, the closest analogue would be:
 
In an Analytica model, if you want to store the "address" of a datum in an array, you would record the index values that specify its coordinates.  To some extent, the closest analogue would be:
[[Slice]](I, row_num)
+
:[[Slice]](I, row_num)
  
which returns the label for the given row.  In an N-D array, you could conceptually construct an array with N elements, one for each dimension.  Analytica's [[ArgMin]] and [[ArgMax]] functions do something along these lines to specify a coordinate when performing the [[ArgMin]] or [[ArgMax]] over more than one dimension.
+
which returns the label for the given row.  In an N-D array, you could conceptually construct an array with ''N'' elements, one for each dimension.  Analytica's [[ArgMin]] and [[ArgMax]] functions do something along these lines to specify a coordinate when performing the [[ArgMin]] or [[ArgMax]] over more than one dimension.
  
 
== AREAS(ranges) ==
 
== AREAS(ranges) ==
  
 
In Excel, this returns the number of multiple areas, for example:
 
In Excel, this returns the number of multiple areas, for example:
AREAS((A3:D10, F3:I10, K3:N10)) → 3
+
:<code>AREAS((A3:D10, F3:I10, K3:N10)) &rarr; 3</code>
  
A common situation where this would be used in a spreadsheet occurs when the data is really three-dimensional, organized as a series of 2-D tables.  The third dimension is reflected as multiple areas.  Thus, in Analytica, the ranges would really be a 3-D array, and the operation being replaced here is asking how many slices are in the third dimension.   If the index for that third dimension in your Analytica model is named ''K'', then Analytica equivalent is thus:
+
A common situation where this would be used in a spreadsheet occurs when the data is really three-dimensional, organized as a series of 2-D tables.  The third dimension is reflected as multiple areas.  Thus, in Analytica, the ranges would really be a 3-D array, and the operation being replaced here is asking how many slices are in the third dimension. If the index for that third dimension in your Analytica model is named ''K'', then Analytica equivalent is thus:
[[Size]](K)
+
:[[Size]](K)
  
 
== CHOOSE(index_num, value1'', value2,...'') ==
 
== CHOOSE(index_num, value1'', value2,...'') ==
Line 27: Line 27:
 
The most general Analytica equivalent is:
 
The most general Analytica equivalent is:
  
  If index_num=1 Then value1
+
<pre style="background:white; border:white; margin-left: 1em;">
  Else If index_num=2 Then value2
+
  If index_num = 1 Then value1
  Else If index_num=3 Then value3
+
  Else If index_num = 2 Then value2
 +
  Else If index_num = 3 Then value3
 
  ...
 
  ...
 
  Else Null
 
  Else Null
 +
</pre>
  
When ''index_num'' is out-of-range, excel returns #VALUE!.  Here we've used Null in place of Value (since #VALUE! does not exist in Analytica).  Alternatively, you might replace Null with the [[Error]] function.
+
When «index_num» is out-of-range, excel returns <code>#VALUE!</code>.  Here we've used [[Null]] in place of Value (since <code>#VALUE!</code> does not exist in Analytica).  Alternatively, you might replace [[Null]] with the [[Error]] function.
  
There are a several other very convenient methods for implementing the equivalent to Choose in Analytica that apply to specific cases.  When ''value1, value2, ...'' all have the same dimensionality, a [[DetermTable]] provides this functionality, where ''value1, value2, ...'' are entered into each cell of the table.  This organization often provides a very nice to use and transparent representation.
+
There are a several other very convenient methods for implementing the equivalent to CHOOSE in Analytica that apply to specific cases.  When «value1, value2, ...» all have the same dimensionality, a [[DetermTable]] provides this functionality, where «value1, value2, ...'» are entered into each cell of the table.  This organization often provides a very nice to use and transparent representation.
  
When the dimensionality of ''value1'' is different from ''value2'', etc., a [[DetermTable]] can still be used where references, e.g., '''\value1''', are placed in each cell of the table.  The users of that variable must [[Using References|de-reference]] the result.  The webinar by Brian Parsonnet, viewable at [http://analyticaonline.com/WebinarArchive/2007-11-08-Tariff-Modeling.wmv Tariff Modeling.wmv], provides a very nice and powerful example of using this structure in a model.
+
When the dimensionality of «value1» is different from «value2», etc., a [[DetermTable]] can still be used where references, e.g., <code>\value1</code>, are placed in each cell of the table.  The users of that variable must [[Using References|de-reference]] the result.  The webinar by Brian Parsonnet, viewable at [http://WebinarArchive.analytica.com/2007-11-08-Tariff-Modeling.wmv Tariff Modeling.wmv], provides a very nice and powerful example of using this structure in a model.
  
 
== COLUMN(range) ==
 
== COLUMN(range) ==
  
 
The closest Analytica equivalent is:
 
The closest Analytica equivalent is:
[[Index Position Operator::@|@]][ColumnIndex = range]
+
:[[Index Position Operator::@|@]][ColumnIndex = range]
  
Excel's Column function is somewhat specific to the spreadsheet paradigm, the an exact equivalent is not entirely applicable.  But the position operator shown here is a close analogue.  In Excel, a range identifies a cell or group of cells.  In Analytica, an index label identifies a position along an index, and an array containing index labels identifies a group of positions.  Thus, if range is a label, or an array of labels, appearing in the ColumnIndex, then ''[[Index Position Operator::@|@[ColumnIndex=range]]]'' returns the column position of that range.
+
Excel's COLUMN function is somewhat specific to the spreadsheet paradigm, the an exact equivalent is not entirely applicable.  But the position operator shown here is a close analogue.  In Excel, a range identifies a cell or group of cells.  In Analytica, an index label identifies a position along an index, and an array containing index labels identifies a group of positions.  Thus, if range is a label, or an array of labels, appearing in the «ColumnIndex», then ''[[Index Position Operator::@|@[ColumnIndex = range]]]'' returns the column position of that range.
  
 
== COLUMNS(array) ==
 
== COLUMNS(array) ==
  
Analytica equivalents:
+
''Analytica equivalents:''
[[Size]](ColumnIndex)
+
:[[Size]](ColumnIndex)
[[Sum]](1, ColumnIndex)
+
:[[Sum]](1, ColumnIndex)
  
 
The block of data referenced by the ''array' cell references in an Excel spreadsheet will typically be stored in a single variable in your Analytica model.  Excel's Column function is basically asking how long that column index is.  The two above forms are equivalent.
 
The block of data referenced by the ''array' cell references in an Excel spreadsheet will typically be stored in a single variable in your Analytica model.  Excel's Column function is basically asking how long that column index is.  The two above forms are equivalent.
Line 56: Line 58:
 
== GETPIVOTDATA(data_field, pivot_table'', field1, item1, field2, item2,...'') ==
 
== GETPIVOTDATA(data_field, pivot_table'', field1, item1, field2, item2,...'') ==
  
Analytica equivalent:
+
''Analytica equivalent:''
A[field1=item1, field2=item2,...]
+
:A[field1 = item1, field2 = item2,...]
where ''A'' is the multi-dimensional array in your Analytica model that corresponds to the data_field of the pivot_table in Excel.  The data_field may not be relevant in your Analytica case, or it may correspond to a particular slice of a report along a particular index, in which case it becomes one additional field that you slice over.
+
where ''A'' is the multi-dimensional array in your Analytica model that corresponds to the «data_field» of the pivot_table in Excel.  The «data_field» may not be relevant in your Analytica case, or it may correspond to a particular slice of a report along a particular index, in which case it becomes one additional field that you [[slice]] over.
  
When certain data_fields within a pivot table are accessed using GetPivotData function in Excel, you may get the grand total over a particular index.  In this case, you would need to apply the [[Sum]] function in your Analytica model as appropriate.
+
When certain «data_field»s within a pivot table are accessed using GetPivotData function in Excel, you may get the grand total over a particular index.  In this case, you would need to apply the [[Sum]] function in your Analytica model as appropriate.
  
 
== HLOOKUP(lookup_value, table_array, row_index_num'', range_lookup'') ==
 
== HLOOKUP(lookup_value, table_array, row_index_num'', range_lookup'') ==
  
Analytica equivalent (when ''range_lookup'' is omitted or false):
+
''Analytica equivalent (when «range_lookup» is omitted or false):''
table_array [ColumnIndex = lookup_value]
+
:table_array [ColumnIndex = lookup_value]
table_array [ColumnIndex = loopup_value, @RowIndex = row_index_num]
+
:table_array [ColumnIndex = loopup_value, @RowIndex = row_index_num]
  
The Analytica equivalent of HLOOKUP and VLOOKUP is the [[Subscript/Slice Operator|subscript operator, A[I=x] ]].  In Excel, your ''table_array'' is a 2-D array, but when you are doing the equivalent in Analytica, you may be working with a 1-D or a 2-D table array.  With HLOOKUP, Excel conceptualizes your table as running horizontally, from left to right.  Analytica doesn't have a notion of it being left-to-right or top-to-bottom, instead Analyica cares only about what index corresponds to that dimension -- in other words, what index are you searching along.  The first form above is appropriate when your table array is 1-D, or when you want the entire slice of the table.  The second form returns the row of interest.  Note that Excel considers the column index to be row 1, so you may need to subtract one from the ''row_index_num''.
+
The Analytica equivalent of HLOOKUP and VLOOKUP is the [[Subscript/Slice Operator|subscript operator, A[I = x]]].  In Excel, your ''table_array'' is a 2-D array, but when you are doing the equivalent in Analytica, you may be working with a 1-D or a 2-D table array.  With HLOOKUP, Excel conceptualizes your table as running horizontally, from left to right.  Analytica doesn't have a notion of it being left-to-right or top-to-bottom, instead Analyica cares only about what index corresponds to that dimension -- in other words, what index are you searching along.  The first form above is appropriate when your table array is 1-D, or when you want the entire slice of the table.  The second form returns the row of interest.  Note that Excel considers the column index to be row 1, so you may need to subtract one from the ''row_index_num''.
  
When ''range_lookup'' is true (approximate match), the equivalents are:
+
When «range_lookup» is true (approximate match), the equivalents are:
[[StepInterp]]( ColumnIndex, table_array, lookup_value, ColumnIndex, LeftLookup:true )
+
:[[StepInterp]](ColumnIndex, table_array, lookup_value, ColumnIndex, LeftLookup: true)
[[StepInterp]]( ColumnIndex, table_array[@RowIndex=row_index_num-1], lookup_value, ColumnIndex, LeftLookup:true )
+
:[[StepInterp]](ColumnIndex, table_array[@RowIndex = row_index_num - 1], lookup_value, ColumnIndex, LeftLookup: true)
  
This form finds the largest value in ColumnIndex that is less or equal to lookup_value.  The first form is appropriate when your ''table_array'' 1-D, or when you want the entire slice for the value found.  The second form is the more faithful equivalent.
+
This form finds the largest value in «ColumnIndex» that is less or equal to «lookup_value».  The first form is appropriate when your ''table_array'' 1-D, or when you want the entire [[slice]] for the value found.  The second form is the more faithful equivalent.
  
 
== HYPERLINK(link_location, friendly_name) ==
 
== HYPERLINK(link_location, friendly_name) ==
  
Hyperlinks in your Analytica document should appear in attributes such as Description, Help, and user-defined attributes, rather than in expressions or definition attributes.  So, instead of using an Analytica function for this, the equivalent is to place the following text within the description attribute of your variable:
+
Hyperlinks in your Analytica document should appear in [[attributes]] such as Description, Help, and user-defined attributes, rather than in [[Expression Syntax|expressions]] or [[definition]] attributes.  So, instead of using an Analytica function for this, the equivalent is to place the following text within the description attribute of your variable:
  
<a href="link_location">friendly_name</a>
+
:<a href="link_location">friendly_name</a>
  
From edit mode, you'll see this HTML-like syntax, but from browse mode, you'll see ''friendly_name'' underlined.  Clicking on it will open the URL or external document (e.g., word file) in a separate web browser or application window.  For example:
+
From edit mode, you'll see this HTML-like syntax, but from browse mode, you'll see «friendly_name» underlined.  Clicking on it will open the URL or external document (e.g., word file) in a separate web browser or application window.  For example:
  
<a href="http://www.lumina.com">Lumina's Web Site</a>
+
:<a href="http://www.lumina.com">Lumina's Web Site</a>
  
 
== INDEX(range, row_num, column_num) ==
 
== INDEX(range, row_num, column_num) ==
  
Analytica equivalent:
+
''Analytica equivalent:''
range [ @RowIndex=row_num, @ColumnIndex = column_num ]
+
:range [@RowIndex=row_num, @ColumnIndex = column_num]
  
When the Index function is used in an Excel spreadsheet, the range parameter normally identifies an entire table somewhere on the spreadsheet.  In Analytica, you should have such a table in its own variable (named ''range'' in the equivalent).
+
When the Index function is used in an Excel spreadsheet, the range parameter normally identifies an entire table somewhere on the spreadsheet.  In Analytica, you should have such a table in its own variable (named «range» in the equivalent).
  
 
Excel has a second variation of the Index function, in which several ranges are specified.  This usage in Excel looks like this:
 
Excel has a second variation of the Index function, in which several ranges are specified.  This usage in Excel looks like this:
Index( (area1,area2,area3,...), row_num, column_num, area_num )
+
:<code>Index((area1, area2, area3,...), row_num, column_num, area_num)</code>
 +
 
 
For example:
 
For example:
Index( (A6:D10, F6:I10, K6:N10), 4, 3, 2 )
+
:<code>Index((A6:D10, F6:I10, K6:N10), 4, 3, 2)</code>
  
When this usage arises, you usually will have a 3-D array in Analyica.  The areas in Excel are slices along the third dimension in the Analyica array.  Thus, the equivalent is (where the array is called ''A''):
+
When this usage arises, you usually will have a 3-D array in Analytica.  The areas in Excel are [[slice]]s along the third dimension in the Analytica array.  Thus, the equivalent is (where the array is called ''A''):
A [ @RowIndex=row_num, @ColumnIndex=column_num, @AreaIndex=area_num ]
+
:A [@RowIndex = row_num, @ColumnIndex = column_num, @AreaIndex = area_num]
  
 
== INDIRECT(ref_text'', a1'') ==
 
== INDIRECT(ref_text'', a1'') ==
Line 107: Line 110:
 
In one variation of this, you have a variable, ''h'', that contains a [[Handle|handle]] to another variable, say ''A''.  Using ''h'', you want to access the value of ''A''.  Hence, you are getting the value of ''A'' indirectly.  This equivalent takes this form:
 
In one variation of this, you have a variable, ''h'', that contains a [[Handle|handle]] to another variable, say ''A''.  Using ''h'', you want to access the value of ''A''.  Hence, you are getting the value of ''A'' indirectly.  This equivalent takes this form:
  
  Variable h := [[Handle]](A)      ''{ Or the handle may be derived from some computation }''
+
:Variable h := [[Handle]](A)      ''{ Or the handle may be derived from some computation }''
 
    
 
    
 
Then to access the value:
 
Then to access the value:
  [[Evaluate]](h)
+
:[[Evaluate]](h)
  
 
A second variation is where you have the name of the variable as a text string.  Here you can use [[Evaluate]] directly:
 
A second variation is where you have the name of the variable as a text string.  Here you can use [[Evaluate]] directly:
  [[Evaluate]]("A")
+
:[[Evaluate]]("A")
This usage entails some perils to watch out for -- in particular, when used in this fashion, Analytica's dependency maintenance mechanism does not know that your result dependended on A.  As a result, should the value of A change in the future, Analytica would not know that your result needs to be recomputed, and it would not get invalidated.
+
 
 +
This usage entails some perils to watch out for -- in particular, when used in this fashion, Analytica's dependency maintenance mechanism does not know that your result depended on ''A''.  As a result, should the value of ''A'' change in the future, Analytica would not know that your result needs to be recomputed, and it would not get invalidated.
  
 
A third variation is a hybrid of the above two:
 
A third variation is a hybrid of the above two:
[[Evaluate]]([[HandleFromIdentifier]]("A"))
+
:[[Evaluate]]([[HandleFromIdentifier]]("A"))
 +
 
 
Again, Analytica does not record the dependency from ''A'' to the result.  The intermediate value here is a [[Handle|handle]], obtained from the text identifier.
 
Again, Analytica does not record the dependency from ''A'' to the result.  The intermediate value here is a [[Handle|handle]], obtained from the text identifier.
  
 
== LOOKUP(lookup_value, lookup_vector, result_vector) ==
 
== LOOKUP(lookup_value, lookup_vector, result_vector) ==
  
Analytica equivalent:
+
''Analytica equivalent:''
StepInterp( lookup_vector, result_vector, lookup_value, I, LeftLookup:true )
+
:StepInterp(lookup_vector, result_vector, lookup_value, I, LeftLookup: true)
where ''I'' is the index common to lookup_vector and result_vector.
+
 
 +
where ''I'' is the index common to «lookup_vector» and «result_vector».
  
 
=== LOOKUP(lookup_value, array) ===
 
=== LOOKUP(lookup_value, array) ===
Line 130: Line 136:
 
This is a strange variation of Lookup in excel, where the search occurs along whichever dimension of array is the longest.  If array has more rows than columns, then the search occurs vertically.
 
This is a strange variation of Lookup in excel, where the search occurs along whichever dimension of array is the longest.  If array has more rows than columns, then the search occurs vertically.
  
When you translate this to Analytica, you will most likely know which dimension the lookup should occur over.  Suppose array is indexed by I and J, and you know the lookup should occur along the I index.  Then the equivalent is:
+
When you translate this to Analytica, you will most likely know which dimension the lookup should occur over.  Suppose array is indexed by ''I'' and ''J'', and you know the lookup should occur along the ''I'' index.  Then the equivalent is:
StepInterp( I, array[@J=size(J)], lookup_value, I, LeftLookup:true )
+
:StepInterp(I, array[@J = size(J)], lookup_value, I, LeftLookup: true)
  
 
== MATCH(lookup_value, lookup_array'', match_type'') ==
 
== MATCH(lookup_value, lookup_array'', match_type'') ==
  
Analytica equivalents when match_type is omitted or -1 are:
+
''Analytica equivalents when match_type is omitted or -1 are:''
[[StepInterp]]( lookup_array, @I, lookup_value, I, LeftLookup:True )
+
:[[StepInterp]](lookup_array, @I, lookup_value, I, LeftLookup: True)
[[CondMax]]( @I, lookup_array<=lookup_value, I )
+
:[[CondMax]](@I, lookup_array <= lookup_value, I)
[[Max]]( [[If]] lookup_array<=lookup_value [[Then]] @I [[Else]] [[Null]], I )
+
:[[Max]]([[If]] lookup_array <= lookup_value [[Then]] @I [[Else]] [[Null]], I)
 +
 
 +
''Analytica equivalent when match_type is 0:''
 +
:[[CondMin]](@I, lookup_array = lookup_value, I)
 +
:[[Min]]([[If]] lookup_array = lookup_value [[Then]] @I [[Else]] [[Null]], I)
  
Analytica equivalent when match_type is 0:
 
[[CondMin]]( @I, lookup_array=lookup_value, I )
 
[[Min]]( [[If]] lookup_array=lookup_value [[Then]] @I [[Else]] [[Null]], I )
 
 
this is also an equivalent when there are no duplicates:
 
this is also an equivalent when there are no duplicates:
[[PositionInIndex]]( lookup_array, lookup_value, I )
+
:[[PositionInIndex]](lookup_array, lookup_value, I)
  
Analytica equivalents when match_type is 1:
+
''Analytica equivalents when match_type is 1:''
[[StepInterp]]( lookup_array, @I, lookup_value, I )
+
:[[StepInterp]](lookup_array, @I, lookup_value, I)
[[CondMin]]( @I, lookup_array>=lookup_value, I )
+
:[[CondMin]](@I, lookup_array >= lookup_value, I )
[[Min]]( [[If]] lookup_array>=lookup_value [[Then]] @I [[Else]] [[Null]], I )
+
:[[Min]]([[If]] lookup_array >= lookup_value [[Then]] @I [[Else]] [[Null]], I)
  
In the match_type<>0 cases, Excel assumes ''lookup_array'' to be in ascending order in the -1 case, or in descending order in the 1 case.  If this is not the case, the [[StepInterp]] Analytica equivalents report an error, while Excel returns a somewhat arbitrary value.  It is hard to know what Excel is actually doing in that case, hence it is hard to specify an Analytica equivalent for those cases.
+
In the «match_type»<>0 cases, Excel assumes ''lookup_array'' to be in ascending order in the -1 case, or in descending order in the 1 case.  If this is not the case, the [[StepInterp]] Analytica equivalents report an error, while Excel returns a somewhat arbitrary value.  It is hard to know what Excel is actually doing in that case, hence it is hard to specify an Analytica equivalent for those cases.
  
When no value in the array matches, Excel returns #N/A.  The different Analytica equivalents shows here differ in what is returned in that case.  For example, in the -1 case, [[StepInterp]] yields 1 or size(I) depending on whether lookup_value is smaller than the smallest, or larger than the largest value in the array.  [[CondMax]] returns -INF, and [[Max]] returns [[Null]].  This behavior when the value is not found is one reason to prefer one Analytica equivalent over another, depending on what would be most convenient in your case.
+
When no value in the array matches, Excel returns #N/A.  The different Analytica equivalents shows here differ in what is returned in that case.  For example, in the -1 case, [[StepInterp]] yields 1 or size(I) depending on whether lookup_value is smaller than the smallest, or larger than the largest value in the array.  [[CondMax]] returns -[[INF]], and [[Max]] returns [[Null]].  This behavior when the value is not found is one reason to prefer one Analytica equivalent over another, depending on what would be most convenient in your case.
  
 
== OFFSET(range, rows, cols'', height, width'') ==
 
== OFFSET(range, rows, cols'', height, width'') ==
  
This function is very specific to the spreadsheet paradigm and has no direct equivalent in Analytica. Generally, however, what Offset is used for is to extract a subset of an array that can then be operated on.  Suppose range is a 2-D array, indexed by I and J, and you wish to extract a certain sub-rectangle of data, say from I = 7..12 and J = 8..14  (the full range of I and J might be 1..100 for example).  You would thus do something like this:
+
This function is very specific to the spreadsheet paradigm and has no direct equivalent in Analytica. Generally, however, what Offset is used for is to extract a subset of an array that can then be operated on.  Suppose range is a 2-D array, indexed by I and J, and you wish to extract a certain sub-rectangle of data, say from <code>I = 7..12</code> and <code>J = 8..14</code> (the full range of <code>I</code> and <code>J</code> might be 1..100 for example).  You would thus do something like this:
  
 +
<pre style="background:white; border:white; margin-left: 1em;">
 
  Index I2 := 7..12;
 
  Index I2 := 7..12;
 
  Index J2 := 8..14;
 
  Index J2 := 8..14;
Line 164: Line 172:
 
  { Do something with subrange, which now a 2-D array, for example: }
 
  { Do something with subrange, which now a 2-D array, for example: }
 
  Sum( Max( subrange,I2 ), J2 )
 
  Sum( Max( subrange,I2 ), J2 )
 +
</pre>
  
 
== ROW ==
 
== ROW ==
  
The closest Analytica equivalent is:
+
''The closest Analytica equivalent is:''
[[Index Position Operator::@|@]][ RowIndex = range ]
+
:[[Index Position Operator::@|@]][RowIndex = range]
  
Excel's Row function is somewhat specific to the spreadsheet paradigm, the an exact equivalent is not entirely applicable.  But the position operator shown here is a close analogue.  In Excel, a range identifies a cell or group of cells.  In Analytica, an index label identifies a position along an index, and an array containing index labels identifies a group of positions.  Thus, if range is a label, or an array of labels, appearing in the RowIndex, then ''[[Index Position Operator::@|@[RowIndex=range]]]'' returns the row position of that range.
+
Excel's ROW function is somewhat specific to the spreadsheet paradigm, the an exact equivalent is not entirely applicable.  But the position operator shown here is a close analogue.  In Excel, a range identifies a cell or group of cells.  In Analytica, an index label identifies a position along an index, and an array containing index labels identifies a group of positions.  Thus, if range is a label, or an array of labels, appearing in the «RowIndex», then ''[[Index Position Operator::@|@[RowIndex = range]]]'' returns the row position of that range.
  
 
== ROWS(array) ==
 
== ROWS(array) ==
  
Analytica equivalents:
+
''Analytica equivalents:''
[[Size]](RowIndex)
+
:[[Size]](RowIndex)
[[Sum]](1,RowIndex)
+
:[[Sum]](1,RowIndex)
  
 
The block of data referenced by the ''array' cell references in an Excel spreadsheet will typically be stored in a single variable in your Analytica model.  Excel's Row function is basically asking how long that row index is.  The two above forms are equivalent.
 
The block of data referenced by the ''array' cell references in an Excel spreadsheet will typically be stored in a single variable in your Analytica model.  Excel's Row function is basically asking how long that row index is.  The two above forms are equivalent.
Line 188: Line 197:
 
In many cases, perhaps most cases where Transpose is used in a spreadsheet, the operation can be skipped entirely in your Analytica model.  This is because the dimensions of an array in Analytica are identified by their index, not by whether they are in the row or column position.  Your expressions specify which dimension you are operating over, and that will automatically allow you to operate on the correct dimension without having to transpose.
 
In many cases, perhaps most cases where Transpose is used in a spreadsheet, the operation can be skipped entirely in your Analytica model.  This is because the dimensions of an array in Analytica are identified by their index, not by whether they are in the row or column position.  Your expressions specify which dimension you are operating over, and that will automatically allow you to operate on the correct dimension without having to transpose.
  
Occassionally, in the case of a square matrix, you may need to transpose the matrix, which in Analytica terms means that you are re-indexing each index with the other.  For that, the Analytica equivalent is:
+
Occasionally, in the case of a square matrix, you may need to transpose the matrix, which in Analytica terms means that you are re-indexing each index with the other.  For that, the Analytica equivalent is:
Transpose(array,I,J)
+
:[[Transpose]](array, I, J)
where I and J are the indexes of the array that are being swapped.
+
where ''I'' and ''J'' are the indexes of «array» that are being swapped.
 +
 
 +
== <div id="VLOOKUP">VLOOKUP(lookup_value, table_array, col_index_num'', range_lookup'')</div> ==
 +
 
 +
''Analytica equivalent (when «range_lookup» is omitted or false):''
 +
:table_array [RowIndex = lookup_value]
 +
:table_array [RowIndex = loopup_value, @ColumnIndex = col_index_num] 
 +
 
 +
The Analytica equivalent of HLOOKUP and VLOOKUP is the [[Subscript/Slice Operator|subscript operator, A[I=x]]].  In Excel, your «table_array» is a 2-D array, but when you are doing the equivalent in Analytica, you may be working with a 1-D or a 2-D table array.  With HLOOKUP, Excel conceptualizes your table as running vertically, from top to bottom.  Analytica doesn't have a notion of it being left-to-right or top-to-bottom, instead Analytica cares only about what index corresponds to that dimension -- in other words, what index are you searching along.  The first form above is appropriate when your table array is 1-D, or when you want the entire slice of the table.  The second form returns the row of interest.  Note that Excel considers the row index to be column 1, so you may need to subtract one from the «col_index_num».
  
== VLOOKUP(lookup_value, table_array, col_index_num'', range_lookup'') ==
+
<center>[[image:Excel_VLookup.png]]</center>
  
Analytica equivalent (when ''range_lookup'' is omitted or false):
+
In Analytica:
table_array [RowIndex = lookup_value]
+
:Index Fruit ::= <code>['Apple','Banana','Cherry','Date','Eggplant','Fig','Grape']</code>
table_array [RowIndex = loopup_value, @ColumnIndex = col_index_num]  
+
:Variable Fruit_prices ::= <code>[[Table]](Fruit)</code>
 +
:Decision Item_to_lookup ::= <code>[[Choice]](Fruit, 3)</code>
 +
:Variable Item_price ::= <code>Fruit_prices [ Fruit = Item_to_lookup ]</code>
  
The Analytica equivalent of HLOOKUP and VLOOKUP is the [[Subscript/Slice Operator|subscript operator, A[I=x] ]].  In Excel, your ''table_array'' is a 2-D array, but when you are doing the equivalent in Analytica, you may be working with a 1-D or a 2-D table array.  With HLOOKUP, Excel conceptualizes your table as running vertically, from top to bottom.  Analytica doesn't have a notion of it being left-to-right or top-to-bottom, instead Analyica cares only about what index corresponds to that dimension -- in other words, what index are you searching along.  The first form above is appropriate when your table array is 1-D, or when you want the entire slice of the table.  The second form returns the row of interest.  Note that Excel considers the row index to be column 1, so you may need to subtract one from the ''col_index_num''.
+
When «range_lookup» is true (approximate match), the equivalents are:
 +
:[[StepInterp]](RowIndex, table_array, lookup_value, RowIndex, LeftLookup: true)
 +
:[[StepInterp]](RowIndex, table_array[@ColumnIndex = row_index_num-1], lookup_value, RowIndex, LeftLookup: true)
  
When ''range_lookup'' is true (approximate match), the equivalents are:
+
This form finds the largest value in «RowIndex» that is less or equal to «lookup_value».  The first form is appropriate when your «table_array» 1-D, or when you want the entire slice for the value found. The second form is the more faithful equivalent.
  [[StepInterp]](RowIndex, table_array, lookup_value, RowIndex, LeftLookup: true)
 
[[StepInterp]](RowIndex, table_array[@ColumnIndex=row_index_num-1], lookup_value, RowIndex, LeftLookup: true)
 
  
This form finds the largest value in RowIndex that is less or equal to lookup_value.  The first form is appropriate when your ''table_array'' 1-D, or when you want the entire slice for the value found.  The second form is the more faithful equivalent.
+
==See Also==
 +
* [[Excel to Analytica Mappings]]

Latest revision as of 15:37, 18 November 2024



ADDRESS(row_num, column_num, abs_num, a1, sheet_text)

Excel's Address function is very specific to the spreadsheet framework, producing a cell address. Analytica models do not have a concept of cell addresses, so this function is not applicable.

In an Analytica model, if you want to store the "address" of a datum in an array, you would record the index values that specify its coordinates. To some extent, the closest analogue would be:

Slice(I, row_num)

which returns the label for the given row. In an N-D array, you could conceptually construct an array with N elements, one for each dimension. Analytica's ArgMin and ArgMax functions do something along these lines to specify a coordinate when performing the ArgMin or ArgMax over more than one dimension.

AREAS(ranges)

In Excel, this returns the number of multiple areas, for example:

AREAS((A3:D10, F3:I10, K3:N10)) → 3

A common situation where this would be used in a spreadsheet occurs when the data is really three-dimensional, organized as a series of 2-D tables. The third dimension is reflected as multiple areas. Thus, in Analytica, the ranges would really be a 3-D array, and the operation being replaced here is asking how many slices are in the third dimension. If the index for that third dimension in your Analytica model is named K, then Analytica equivalent is thus:

Size(K)

CHOOSE(index_num, value1, value2,...)

The most general Analytica equivalent is:

 If index_num = 1 Then value1
 Else If index_num = 2 Then value2
 Else If index_num = 3 Then value3
 ...
 Else Null

When «index_num» is out-of-range, excel returns #VALUE!. Here we've used Null in place of Value (since #VALUE! does not exist in Analytica). Alternatively, you might replace Null with the Error function.

There are a several other very convenient methods for implementing the equivalent to CHOOSE in Analytica that apply to specific cases. When «value1, value2, ...» all have the same dimensionality, a DetermTable provides this functionality, where «value1, value2, ...'» are entered into each cell of the table. This organization often provides a very nice to use and transparent representation.

When the dimensionality of «value1» is different from «value2», etc., a DetermTable can still be used where references, e.g., \value1, are placed in each cell of the table. The users of that variable must de-reference the result. The webinar by Brian Parsonnet, viewable at Tariff Modeling.wmv, provides a very nice and powerful example of using this structure in a model.

COLUMN(range)

The closest Analytica equivalent is:

@[ColumnIndex = range]

Excel's COLUMN function is somewhat specific to the spreadsheet paradigm, the an exact equivalent is not entirely applicable. But the position operator shown here is a close analogue. In Excel, a range identifies a cell or group of cells. In Analytica, an index label identifies a position along an index, and an array containing index labels identifies a group of positions. Thus, if range is a label, or an array of labels, appearing in the «ColumnIndex», then @[ColumnIndex = range] returns the column position of that range.

COLUMNS(array)

Analytica equivalents:

Size(ColumnIndex)
Sum(1, ColumnIndex)

The block of data referenced by the array' cell references in an Excel spreadsheet will typically be stored in a single variable in your Analytica model. Excel's Column function is basically asking how long that column index is. The two above forms are equivalent.

GETPIVOTDATA(data_field, pivot_table, field1, item1, field2, item2,...)

Analytica equivalent:

A[field1 = item1, field2 = item2,...]

where A is the multi-dimensional array in your Analytica model that corresponds to the «data_field» of the pivot_table in Excel. The «data_field» may not be relevant in your Analytica case, or it may correspond to a particular slice of a report along a particular index, in which case it becomes one additional field that you slice over.

When certain «data_field»s within a pivot table are accessed using GetPivotData function in Excel, you may get the grand total over a particular index. In this case, you would need to apply the Sum function in your Analytica model as appropriate.

HLOOKUP(lookup_value, table_array, row_index_num, range_lookup)

Analytica equivalent (when «range_lookup» is omitted or false):

table_array [ColumnIndex = lookup_value]
table_array [ColumnIndex = loopup_value, @RowIndex = row_index_num]

The Analytica equivalent of HLOOKUP and VLOOKUP is the subscript operator, A[I = x]. In Excel, your table_array is a 2-D array, but when you are doing the equivalent in Analytica, you may be working with a 1-D or a 2-D table array. With HLOOKUP, Excel conceptualizes your table as running horizontally, from left to right. Analytica doesn't have a notion of it being left-to-right or top-to-bottom, instead Analyica cares only about what index corresponds to that dimension -- in other words, what index are you searching along. The first form above is appropriate when your table array is 1-D, or when you want the entire slice of the table. The second form returns the row of interest. Note that Excel considers the column index to be row 1, so you may need to subtract one from the row_index_num.

When «range_lookup» is true (approximate match), the equivalents are:

StepInterp(ColumnIndex, table_array, lookup_value, ColumnIndex, LeftLookup: true)
StepInterp(ColumnIndex, table_array[@RowIndex = row_index_num - 1], lookup_value, ColumnIndex, LeftLookup: true)

This form finds the largest value in «ColumnIndex» that is less or equal to «lookup_value». The first form is appropriate when your table_array 1-D, or when you want the entire slice for the value found. The second form is the more faithful equivalent.

HYPERLINK(link_location, friendly_name)

Hyperlinks in your Analytica document should appear in attributes such as Description, Help, and user-defined attributes, rather than in expressions or definition attributes. So, instead of using an Analytica function for this, the equivalent is to place the following text within the description attribute of your variable:

<a href="link_location">friendly_name</a>

From edit mode, you'll see this HTML-like syntax, but from browse mode, you'll see «friendly_name» underlined. Clicking on it will open the URL or external document (e.g., word file) in a separate web browser or application window. For example:

<a href="http://www.lumina.com">Lumina's Web Site</a>

INDEX(range, row_num, column_num)

Analytica equivalent:

range [@RowIndex=row_num, @ColumnIndex = column_num]

When the Index function is used in an Excel spreadsheet, the range parameter normally identifies an entire table somewhere on the spreadsheet. In Analytica, you should have such a table in its own variable (named «range» in the equivalent).

Excel has a second variation of the Index function, in which several ranges are specified. This usage in Excel looks like this:

Index((area1, area2, area3,...), row_num, column_num, area_num)

For example:

Index((A6:D10, F6:I10, K6:N10), 4, 3, 2)

When this usage arises, you usually will have a 3-D array in Analytica. The areas in Excel are slices along the third dimension in the Analytica array. Thus, the equivalent is (where the array is called A):

A [@RowIndex = row_num, @ColumnIndex = column_num, @AreaIndex = area_num]

INDIRECT(ref_text, a1)

There are a couple Analytica equivalents, depending specifically on what you are doing.

In one variation of this, you have a variable, h, that contains a handle to another variable, say A. Using h, you want to access the value of A. Hence, you are getting the value of A indirectly. This equivalent takes this form:

Variable h := Handle(A) { Or the handle may be derived from some computation }

Then to access the value:

Evaluate(h)

A second variation is where you have the name of the variable as a text string. Here you can use Evaluate directly:

Evaluate("A")

This usage entails some perils to watch out for -- in particular, when used in this fashion, Analytica's dependency maintenance mechanism does not know that your result depended on A. As a result, should the value of A change in the future, Analytica would not know that your result needs to be recomputed, and it would not get invalidated.

A third variation is a hybrid of the above two:

Evaluate(HandleFromIdentifier("A"))

Again, Analytica does not record the dependency from A to the result. The intermediate value here is a handle, obtained from the text identifier.

LOOKUP(lookup_value, lookup_vector, result_vector)

Analytica equivalent:

StepInterp(lookup_vector, result_vector, lookup_value, I, LeftLookup: true)

where I is the index common to «lookup_vector» and «result_vector».

LOOKUP(lookup_value, array)

This is a strange variation of Lookup in excel, where the search occurs along whichever dimension of array is the longest. If array has more rows than columns, then the search occurs vertically.

When you translate this to Analytica, you will most likely know which dimension the lookup should occur over. Suppose array is indexed by I and J, and you know the lookup should occur along the I index. Then the equivalent is:

StepInterp(I, array[@J = size(J)], lookup_value, I, LeftLookup: true)

MATCH(lookup_value, lookup_array, match_type)

Analytica equivalents when match_type is omitted or -1 are:

StepInterp(lookup_array, @I, lookup_value, I, LeftLookup: True)
CondMax(@I, lookup_array <= lookup_value, I)
Max(If lookup_array <= lookup_value Then @I Else Null, I)

Analytica equivalent when match_type is 0:

CondMin(@I, lookup_array = lookup_value, I)
Min(If lookup_array = lookup_value Then @I Else Null, I)

this is also an equivalent when there are no duplicates:

PositionInIndex(lookup_array, lookup_value, I)

Analytica equivalents when match_type is 1:

StepInterp(lookup_array, @I, lookup_value, I)
CondMin(@I, lookup_array >= lookup_value, I )
Min(If lookup_array >= lookup_value Then @I Else Null, I)

In the «match_type»<>0 cases, Excel assumes lookup_array to be in ascending order in the -1 case, or in descending order in the 1 case. If this is not the case, the StepInterp Analytica equivalents report an error, while Excel returns a somewhat arbitrary value. It is hard to know what Excel is actually doing in that case, hence it is hard to specify an Analytica equivalent for those cases.

When no value in the array matches, Excel returns #N/A. The different Analytica equivalents shows here differ in what is returned in that case. For example, in the -1 case, StepInterp yields 1 or size(I) depending on whether lookup_value is smaller than the smallest, or larger than the largest value in the array. CondMax returns -INF, and Max returns Null. This behavior when the value is not found is one reason to prefer one Analytica equivalent over another, depending on what would be most convenient in your case.

OFFSET(range, rows, cols, height, width)

This function is very specific to the spreadsheet paradigm and has no direct equivalent in Analytica. Generally, however, what Offset is used for is to extract a subset of an array that can then be operated on. Suppose range is a 2-D array, indexed by I and J, and you wish to extract a certain sub-rectangle of data, say from I = 7..12 and J = 8..14 (the full range of I and J might be 1..100 for example). You would thus do something like this:

 Index I2 := 7..12;
 Index J2 := 8..14;
 Variable subrange := range[I=I2,J=J2];
 { Do something with subrange, which now a 2-D array, for example: }
 Sum( Max( subrange,I2 ), J2 )

ROW

The closest Analytica equivalent is:

@[RowIndex = range]

Excel's ROW function is somewhat specific to the spreadsheet paradigm, the an exact equivalent is not entirely applicable. But the position operator shown here is a close analogue. In Excel, a range identifies a cell or group of cells. In Analytica, an index label identifies a position along an index, and an array containing index labels identifies a group of positions. Thus, if range is a label, or an array of labels, appearing in the «RowIndex», then @[RowIndex = range] returns the row position of that range.

ROWS(array)

Analytica equivalents:

Size(RowIndex)
Sum(1,RowIndex)

The block of data referenced by the array' cell references in an Excel spreadsheet will typically be stored in a single variable in your Analytica model. Excel's Row function is basically asking how long that row index is. The two above forms are equivalent.

RTD

There is no Analytica equivalent at this time. To interface with the external program from Analytica, you will probably want to use RunConsoleProcess.

TRANSPOSE(array)

In many cases, perhaps most cases where Transpose is used in a spreadsheet, the operation can be skipped entirely in your Analytica model. This is because the dimensions of an array in Analytica are identified by their index, not by whether they are in the row or column position. Your expressions specify which dimension you are operating over, and that will automatically allow you to operate on the correct dimension without having to transpose.

Occasionally, in the case of a square matrix, you may need to transpose the matrix, which in Analytica terms means that you are re-indexing each index with the other. For that, the Analytica equivalent is:

Transpose(array, I, J)

where I and J are the indexes of «array» that are being swapped.

VLOOKUP(lookup_value, table_array, col_index_num, range_lookup)

Analytica equivalent (when «range_lookup» is omitted or false):

table_array [RowIndex = lookup_value]
table_array [RowIndex = loopup_value, @ColumnIndex = col_index_num]

The Analytica equivalent of HLOOKUP and VLOOKUP is the subscript operator, A[I=x]. In Excel, your «table_array» is a 2-D array, but when you are doing the equivalent in Analytica, you may be working with a 1-D or a 2-D table array. With HLOOKUP, Excel conceptualizes your table as running vertically, from top to bottom. Analytica doesn't have a notion of it being left-to-right or top-to-bottom, instead Analytica cares only about what index corresponds to that dimension -- in other words, what index are you searching along. The first form above is appropriate when your table array is 1-D, or when you want the entire slice of the table. The second form returns the row of interest. Note that Excel considers the row index to be column 1, so you may need to subtract one from the «col_index_num».

Excel VLookup.png

In Analytica:

Index Fruit ::= ['Apple','Banana','Cherry','Date','Eggplant','Fig','Grape']
Variable Fruit_prices ::= Table(Fruit)
Decision Item_to_lookup ::= Choice(Fruit, 3)
Variable Item_price ::= Fruit_prices [ Fruit = Item_to_lookup ]

When «range_lookup» is true (approximate match), the equivalents are:

StepInterp(RowIndex, table_array, lookup_value, RowIndex, LeftLookup: true)
StepInterp(RowIndex, table_array[@ColumnIndex = row_index_num-1], lookup_value, RowIndex, LeftLookup: true)

This form finds the largest value in «RowIndex» that is less or equal to «lookup_value». The first form is appropriate when your «table_array» 1-D, or when you want the entire slice for the value found. The second form is the more faithful equivalent.

See Also

Comments


You are not allowed to post comments.