Difference between revisions of "Associative vs. Positional Indexing"

m (Cleaned up table style)
 
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
[[Category:Concepts]]
+
[[Category:Arrays]]
 
[[Category:Doc Status C]] <!-- For Lumina use, do not change -->
 
[[Category:Doc Status C]] <!-- For Lumina use, do not change -->
  
When accessing array elements from Analyica expressions, we must identify which position along an index that we wish to access.  In Analytica, this can usually be done either associatively or positionally.
 
  
Suppose Index Year has the following elements:
+
__TOC__
  
Year&rarr;
+
When accessing an element of an array elements, you can identify the element by '''''association '''''or '''''position'''''.
{| class="wikitable"
+
 
 +
Suppose Index <code>Year</code> has these elements:
 +
 
 +
:<code>Index Year :=</code>
 +
:{| class="wikitable"
 
| 2007 || 2008 || 2009 || 2010 || 2011 || 2012  
 
| 2007 || 2008 || 2009 || 2010 || 2011 || 2012  
 
|}
 
|}
  
And variable Earnings evaluates to an array indexed by Year,
+
And variable <code>Earnings</code> is an array indexed by <code>Year</code>
  
{| class="wikitable"
+
:<code>Variable Earnings :=</code>
! Year &rarr; !! 2007 !! 2008 !! 2009 !! 2010 !! 2011 !! 2012
+
:{| class="wikitable"
 +
! colspan="6" | Year &#9654;
 
|-
 
|-
!Earnings&rarr; || 4.5M || 5.6M || 6.6M || 7.9M || 9.0M || 10.1M
+
! 2007 !! 2008 !! 2009 !! 2010 !! 2011 !! 2012
 +
|-
 +
| 4.5M || 5.6M || 6.6M || 7.9M || 9.0M || 10.1M
 
|}
 
|}
  
Then we can access particular elements of Earnings either associatively:
+
Then we can access an element of Earnings by association:
:[[Subscript/Slice Operator|Earnings[Year=2009] ]] &rarr; 6.6M
+
:<code>Earnings[Year = 2009] &rarr; 6.6M</code>
 
or by position:
 
or by position:
:[[Subscript/Slice Operator|Earnings[@Year=3] ]] &rarr; 6.6M
+
:<code>Earnings[@Year = 3] &rarr; 6.6M</code>
  
Referring to an index element associatively is generally refered to as ''subscripting'', and can also be accomplished using the [[Subscript]] function, which is equivalent to the above, e.g.:
+
We sometimes term indexing by '''''associati'''''on as [[Subscript/Slice Operator|subscripting]], because you can use the [[Subscript]] function, which is equivalent to the above, e.g.:
:[[Subscript]](Earnings,Year,2009) &rarr; 6.6M
+
:<code>Subscript(Earnings, Year, 2009) &rarr; 6.6M</code>
Referring to an index element by position is called ''slicing'', and can equivalently be accomplished using the [[Slice]] function, e.g.:
+
And we sometimes term indexing by '''''position''''' as [[Subscript/Slice Operator|slicing]], because you can use  [[Slice]] function, which is equivalent to the positional indexing, e.g.:
:[[Slice]](Earnings,Year,3) &rarr; 6.6M
+
:<code>Slice(Earnings, Year, 3) &rarr; 6.6M</code>
  
Positions in Analytica are always 1-based, and range from 1 to [[Size]](I).
+
Positions in Analytica go from 1 up to [[Size]](I).
  
For text elements, associational lookup is case-sensitive, i.e., A[L='low'] is not the same as A[L='Low'].
+
For text elements, indexing by association is case-sensitive, e.g., <code>A[L = 'low']</code> is not the same as <code>A[L = 'Low']</code>.
  
= Associative / Positional Duals =
+
== Associative / Positional Duals ==
  
Tare many functions that either require an index element be specified, or return an index position or element.  Most built-in functions that identify to an index element associationally have a positional dual, and vise versa.  The following table indicates associational / positional duals.
+
Most built-in functions that identify an index element by association also have a positional option, and vice versa, as shown here:
  
{| class="wikitable"
+
:{| class="wikitable"
|+ Associational / Positional Duals
+
! Associational !! Positional || Notes
! Associational !! By Position || Notes
 
 
|-
 
|-
| [[Subscript/Slice Operator|A[I=x] ]] || [[Subscript/Slice Operator|A[@I=n] ]] || &nbsp;
+
| [[Subscript/Slice Operator|A[I = x] ]] || [[Subscript/Slice Operator|A[@I = n] ]] || &nbsp;
 
|-
 
|-
| [[Subscript/Slice Operator|A[I=J] ]] || [[Subscript/Slice Operator|A[@I=@J] ]] || variation refered to as re-indexing
+
| [[Subscript/Slice Operator|A[I = J] ]] || [[Subscript/Slice Operator|A[@I = @J] ]] || Variation referred to as ''re-indexing''
 
|-
 
|-
| [[Subscript]](A,I,x) || [[Slice]](A,I,n) || &nbsp;
+
| [[Subscript]](A, I, x) || [[Slice]](A, I, n) || &nbsp;
 
|-
 
|-
| [[Slice]](I,n) || [[Index Position Operator::@|@[I=x] ]] || [[Slice]](I,n) : returns the nth element of an index.
+
| [[Slice]](I, n) || [[Index Position Operator::@|@[I = x] ]] || [[Slice]](I, n) : returns the «n»th element of an index.
[[Index Position Operator::@|@[I=x] ]] : returns the position of element x in an index.
+
[[Index Position Operator::@|@[I=x] ]] : returns the position of element «x» in an index.
 
|-
 
|-
| [[ArgMax]](A,I) || [[ArgMax]](A,I,position:true) || &nbsp;
+
| [[ArgMax]](A, I) || [[ArgMax]](A, I, position: True) || &nbsp;
 
|-
 
|-
| [[ArgMin]](A,I) || [[ArgMin]](A,I,position:true) || &nbsp;
+
| [[ArgMin]](A, I) || [[ArgMin]](A, I, position: True) || &nbsp;
 
|-
 
|-
| [[Choice]](I,n) || [[Choice]](I,n,result:I) || The second parameter is always positional.   
+
| [[Choice]](I, n) || [[Choice]](I, n, result: @I) || The second parameter is always positional.   
The return value here is the element of I or the position along I.
+
The return value here is the element of «I» or the position along «I».
 
|-
 
|-
| [[For..Do|For]] x:=I Do... || [[For..Do|For]] n:=[[Position operator|@I]] Do... || &nbsp;
+
| [[For..Do|For]] x:=I Do... || [[For..Do|For]] n := [[Position operator|@I]] Do... || &nbsp;
 
|-
 
|-
 
| [[IndexValue]](I) || [[Position operator|@I]]
 
| [[IndexValue]](I) || [[Position operator|@I]]
 
| The elements of an index or the position along an index.
 
| The elements of an index or the position along an index.
 
|-
 
|-
| [[SubIndex]](A,U,I) || [[PositionInIndex]](A,U,I) || &nbsp;
+
| [[SubIndex]](A, U, I) || [[PositionInIndex]](A, U, I) || &nbsp;
 
|-
 
|-
| (no equiv) || [[Rank]](A,I) || [[Rank]] is related to [[SortIndex]], which returns positions.
+
| (no equiv) || [[Rank]](A, I) || [[Rank]] is related to [[SortIndex]], which returns positions.
 
There is no logical associational dual.
 
There is no logical associational dual.
 
|-
 
|-
| [[SortIndex]](A,I) ||  [[Index..Do|Index]] J:=@I Do [[SortIndex]](A[@I=@J],J) || no built-in positional dual  
+
| [[SortIndex]](A, I) ||  [[Index..Do|Index]] J := @I Do [[SortIndex]](A[@I = @J], J) || No built-in positional dual  
 
|-
 
|-
 
| [[Subset]](D)  
 
| [[Subset]](D)  
| In Analytica 4.2 or better:
+
|
:[[Subset]](D,position:true)
+
:[[Subset]](D, position: true)
In Analytica 4.1 or earlier:
 
:[[Index..Do|Index]] I:=1..[[Size]](D) Do [[Subset]]([[Array]](I,D))  
 
 
| D must be 1-D.  
 
| D must be 1-D.  
 
No built-in positional dual prior to release 4.2.
 
No built-in positional dual prior to release 4.2.
 
|-
 
|-
| [[Unique]](A,I) || [[Unique]](A,I,position:true) || Only works in Analytica 4.0 and above.
+
| [[Unique]](A, I) || [[Unique]](A, I, position: true) || Only works in Analytica 4.0 and above.
 
|}
 
|}
  
= When to Use Assocational vs. Positional =
+
== When to Index by Association vs. Position ==
  
Here we consider when it is preferable to use associational (subscript) indexing, when is it better to use positional (slice) indexing, and when ''must'' you use one or the other.
+
Indexing by Association (subscript) is generally more flexible.  If you insert a new element into an index, say <code>Division</code>, this expression
 +
:<code>Expenses[Division = 'Marketing']</code>
 +
continues to refer to the correct data, where the positional equivalent, <code>Expenses[@Division = 6]</code>, would break if 'Marketing' is no longer the 6th element.
  
Associational (subscript) indexing is the more commonly used in variable definitions because it tends to result in more flexible modelsIf a new element it inserted into an index, say Division, expressions such as
+
On the other hand, if an index has duplicate elements, indexing by association is ambiguousIn this case, you need to index by position to avoid the ambiguity.  For this reason, it's often better to use positional indexing in [[User-Defined Functions]], if you can't assume an index has unique elements. It is usually poor practice to create indexes with duplicate elements, but there are occasionally legitimate cases.
Expenses[Division='Marketing']
 
continue to refer to the correct data, while the positional dual, Expenses[@Division=6], would break in such a case.
 
  
On the other hand, if an index has, or potentially may have, duplicate elements, then associational indexing is ambiguousIn this case, positional indexing is required to avoid the abiguityFor this reason, positional indexing is often preferred in the definitions of [[User-Defined Functions]], where you may not want to assume uniqueness of elements in an index.  It is usually a poor practice to create indexes with duplicate elements, but there are occassionally legitimate cases for having non-unique elements.
+
A second case where positional indexing is appropriate is when using a square matrixA square matrix must have two indexes of the same lengthIf you can be sure that the two indexes have the same elements, indexing by association works fine, but in the more general case you can only assume the same length but not identical values, you should index by position.
  
A second case where positional indexing is appropriate is when dealing with square matriciesSquare matricies have two indexes of the same lengthIf you can be certain that the two indexes have exactly the same elements, then associational indexes works fine, but in the more general case where only the length can be assumed, then positional indexing must be used.
+
Finally, some operations are inherently positional or associational by the nature of what is being doneFor example, referring the the previous element of an array, <code>A[@I = @I-1]</code>, is inherently positionalAn "outer join" of two arrays, such as <code>Salary_by_paygrade[Person = Paygrade_by_person]</code>, is naturally associational.
  
Finally, some operations are inherently positional or associational by the nature of what is being done.  For example, refering the the previous element of an array, A[@I=@I-1], is inherently positional.  An "outer join" of two arrays, such as Salary_by_paygrade[Person=Paygrade_by_person], is naturally associational.
+
== Table Splicing ==
 
 
= [[Table Splicing]] =
 
  
 
When an index changes, perhaps because a user inserted or deleted elements, or because something impacting the computation of its [[IndexValue]] changed, [[Table|edit tables]] based on that index must be spliced.  This means that rows may need to be moved around, deleted, or added (with empty or default values).  This modification of existing edit tables is referred to as [[Table Splicing|splicing]].   
 
When an index changes, perhaps because a user inserted or deleted elements, or because something impacting the computation of its [[IndexValue]] changed, [[Table|edit tables]] based on that index must be spliced.  This means that rows may need to be moved around, deleted, or added (with empty or default values).  This modification of existing edit tables is referred to as [[Table Splicing|splicing]].   
  
 
For a given index, you can specify whether tables that depend on it should splice associationally or positionally when the index value changes.  See [[Table Splicing]] for more information.
 
For a given index, you can specify whether tables that depend on it should splice associationally or positionally when the index value changes.  See [[Table Splicing]] for more information.
 +
 +
==See Also==
 +
* [[Table Splicing]]
 +
* [[Position operator]]
 +
* [[Index Position Operator::@]]

Latest revision as of 19:36, 18 March 2016


When accessing an element of an array elements, you can identify the element by association or position.

Suppose Index Year has these elements:

Index Year :=
2007 2008 2009 2010 2011 2012

And variable Earnings is an array indexed by Year

Variable Earnings :=
Year ▶
2007 2008 2009 2010 2011 2012
4.5M 5.6M 6.6M 7.9M 9.0M 10.1M

Then we can access an element of Earnings by association:

Earnings[Year = 2009] → 6.6M

or by position:

Earnings[@Year = 3] → 6.6M

We sometimes term indexing by association as subscripting, because you can use the Subscript function, which is equivalent to the above, e.g.:

Subscript(Earnings, Year, 2009) → 6.6M

And we sometimes term indexing by position as slicing, because you can use Slice function, which is equivalent to the positional indexing, e.g.:

Slice(Earnings, Year, 3) → 6.6M

Positions in Analytica go from 1 up to Size(I).

For text elements, indexing by association is case-sensitive, e.g., A[L = 'low'] is not the same as A[L = 'Low'].

Associative / Positional Duals

Most built-in functions that identify an index element by association also have a positional option, and vice versa, as shown here:

Associational Positional Notes
A[I = x] A[@I = n]  
A[I = J] A[@I = @J] Variation referred to as re-indexing
Subscript(A, I, x) Slice(A, I, n)  
Slice(I, n) @[I = x] Slice(I, n) : returns the «n»th element of an index.

@[I=x]  : returns the position of element «x» in an index.

ArgMax(A, I) ArgMax(A, I, position: True)  
ArgMin(A, I) ArgMin(A, I, position: True)  
Choice(I, n) Choice(I, n, result: @I) The second parameter is always positional.

The return value here is the element of «I» or the position along «I».

For x:=I Do... For n := @I Do...  
IndexValue(I) @I The elements of an index or the position along an index.
SubIndex(A, U, I) PositionInIndex(A, U, I)  
(no equiv) Rank(A, I) Rank is related to SortIndex, which returns positions.

There is no logical associational dual.

SortIndex(A, I) Index J := @I Do SortIndex(A[@I = @J], J) No built-in positional dual
Subset(D)
Subset(D, position: true)
D must be 1-D.

No built-in positional dual prior to release 4.2.

Unique(A, I) Unique(A, I, position: true) Only works in Analytica 4.0 and above.

When to Index by Association vs. Position

Indexing by Association (subscript) is generally more flexible. If you insert a new element into an index, say Division, this expression

Expenses[Division = 'Marketing']

continues to refer to the correct data, where the positional equivalent, Expenses[@Division = 6], would break if 'Marketing' is no longer the 6th element.

On the other hand, if an index has duplicate elements, indexing by association is ambiguous. In this case, you need to index by position to avoid the ambiguity. For this reason, it's often better to use positional indexing in User-Defined Functions, if you can't assume an index has unique elements. It is usually poor practice to create indexes with duplicate elements, but there are occasionally legitimate cases.

A second case where positional indexing is appropriate is when using a square matrix. A square matrix must have two indexes of the same length. If you can be sure that the two indexes have the same elements, indexing by association works fine, but in the more general case you can only assume the same length but not identical values, you should index by position.

Finally, some operations are inherently positional or associational by the nature of what is being done. For example, referring the the previous element of an array, A[@I = @I-1], is inherently positional. An "outer join" of two arrays, such as Salary_by_paygrade[Person = Paygrade_by_person], is naturally associational.

Table Splicing

When an index changes, perhaps because a user inserted or deleted elements, or because something impacting the computation of its IndexValue changed, edit tables based on that index must be spliced. This means that rows may need to be moved around, deleted, or added (with empty or default values). This modification of existing edit tables is referred to as splicing.

For a given index, you can specify whether tables that depend on it should splice associationally or positionally when the index value changes. See Table Splicing for more information.

See Also

Comments


You are not allowed to post comments.