calc: Manipulating Vectors

 
 10.4 Manipulating Vectors
 =========================
 
 The ‘v l’ (‘calc-vlength’) [‘vlen’] command computes the length of a
 vector.  The length of a non-vector is considered to be zero.  Note that
 matrices are just vectors of vectors for the purposes of this command.
 
    With the Hyperbolic flag, ‘H v l’ [‘mdims’] computes a vector of the
 dimensions of a vector, matrix, or higher-order object.  For example,
 ‘mdims([[a,b,c],[d,e,f]])’ returns ‘[2, 3]’ since its argument is a 2x3
 matrix.
 
    The ‘v f’ (‘calc-vector-find’) [‘find’] command searches along a
 vector for the first element equal to a given target.  The target is on
 the top of the stack; the vector is in the second-to-top position.  If a
 match is found, the result is the index of the matching element.
 Otherwise, the result is zero.  The numeric prefix argument, if given,
 allows you to select any starting index for the search.
 
    The ‘v a’ (‘calc-arrange-vector’) [‘arrange’] command rearranges a
 vector to have a certain number of columns and rows.  The numeric prefix
 argument specifies the number of columns; if you do not provide an
 argument, you will be prompted for the number of columns.  The vector or
 matrix on the top of the stack is “flattened” into a plain vector.  If
 the number of columns is nonzero, this vector is then formed into a
 matrix by taking successive groups of N elements.  If the number of
 columns does not evenly divide the number of elements in the vector, the
 last row will be short and the result will not be suitable for use as a
 matrix.  For example, with the matrix ‘[[1, 2], [3, 4]]’ on the stack,
 ‘v a 4’ produces ‘[[1, 2, 3, 4]]’ (a 1x4 matrix), ‘v a 1’ produces
 ‘[[1], [2], [3], [4]]’ (a 4x1 matrix), ‘v a 2’ produces ‘[[1, 2], [3,
 4]]’ (the original 2x2 matrix), ‘v a 3’ produces ‘[[1, 2, 3], [4]]’ (not
 a matrix), and ‘v a 0’ produces the flattened list ‘[1, 2, 3, 4]’.
 
    The ‘V S’ (‘calc-sort’) [‘sort’] command sorts the elements of a
 vector into increasing order.  Real numbers, real infinities, and
 constant interval forms come first in this ordering; next come other
 kinds of numbers, then variables (in alphabetical order), then finally
 come formulas and other kinds of objects; these are sorted according to
 a kind of lexicographic ordering with the useful property that one
 vector is less or greater than another if the first corresponding
 unequal elements are less or greater, respectively.  Since quoted
 strings are stored by Calc internally as vectors of ASCII character
 codes (SeeStrings), this means vectors of strings are also sorted
 into alphabetical order by this command.
 
    The ‘I V S’ [‘rsort’] command sorts a vector into decreasing order.
 
    The ‘V G’ (‘calc-grade’) [‘grade’, ‘rgrade’] command produces an
 index table or permutation vector which, if applied to the input vector
 (as the index of ‘C-u v r’, say), would sort the vector.  A permutation
 vector is just a vector of integers from 1 to N, where each integer
 occurs exactly once.  One application of this is to sort a matrix of
 data rows using one column as the sort key; extract that column, grade
 it with ‘V G’, then use the result to reorder the original matrix with
 ‘C-u v r’.  Another interesting property of the ‘V G’ command is that,
 if the input is itself a permutation vector, the result will be the
 inverse of the permutation.  The inverse of an index table is a rank
 table, whose Kth element says where the Kth original vector element will
 rest when the vector is sorted.  To get a rank table, just use ‘V G V
 G’.
 
    With the Inverse flag, ‘I V G’ produces an index table that would
 sort the input into decreasing order.  Note that ‘V S’ and ‘V G’ use a
 “stable” sorting algorithm, i.e., any two elements which are equal will
 not be moved out of their original order.  Generally there is no way to
 tell with ‘V S’, since two elements which are equal look the same, but
 with ‘V G’ this can be an important issue.  In the matrix-of-rows
 example, suppose you have names and telephone numbers as two columns and
 you wish to sort by phone number primarily, and by name when the numbers
 are equal.  You can sort the data matrix by names first, and then again
 by phone numbers.  Because the sort is stable, any two rows with equal
 phone numbers will remain sorted by name even after the second sort.
 
    The ‘V H’ (‘calc-histogram’) [‘histogram’] command builds a histogram
 of a vector of numbers.  Vector elements are assumed to be integers or
 real numbers in the range [0..N) for some “number of bins” N, which is
 the numeric prefix argument given to the command.  The result is a
 vector of N counts of how many times each value appeared in the original
 vector.  Non-integers in the input are rounded down to integers.  Any
 vector elements outside the specified range are ignored.  (You can tell
 if elements have been ignored by noting that the counts in the result
 vector don’t add up to the length of the input vector.)
 
    If no prefix is given, then you will be prompted for a vector which
 will be used to determine the bins.  (If a positive integer is given at
 this prompt, it will be still treated as if it were given as a prefix.)
 Each bin will consist of the interval of numbers closest to the
 corresponding number of this new vector; if the vector ‘[a, b, c, ...]’
 is entered at the prompt, the bins will be ‘(-inf, (a+b)/2]’, ‘((a+b)/2,
 (b+c)/2]’, etc.  The result of this command will be a vector counting
 how many elements of the original vector are in each bin.
 
    The result will then be a vector with the same length as this new
 vector; each element of the new vector will be replaced by the number of
 elements of the original vector which are closest to it.
 
    With the Hyperbolic flag, ‘H V H’ pulls two vectors from the stack.
 The second-to-top vector is the list of numbers as before.  The top
 vector is an equal-sized list of “weights” to attach to the elements of
 the data vector.  For example, if the first data element is 4.2 and the
 first weight is 10, then 10 will be added to bin 4 of the result vector.
 Without the hyperbolic flag, every element has a weight of one.
 
    The ‘v t’ (‘calc-transpose’) [‘trn’] command computes the transpose
 of the matrix at the top of the stack.  If the argument is a plain
 vector, it is treated as a row vector and transposed into a one-column
 matrix.
 
    The ‘v v’ (‘calc-reverse-vector’) [‘rev’] command reverses a vector
 end-for-end.  Given a matrix, it reverses the order of the rows.  (To
 reverse the columns instead, just use ‘v t v v v t’.  The same principle
 can be used to apply other vector commands to the columns of a matrix.)
 
    The ‘v m’ (‘calc-mask-vector’) [‘vmask’] command uses one vector as a
 mask to extract elements of another vector.  The mask is in the
 second-to-top position; the target vector is on the top of the stack.
 These vectors must have the same length.  The result is the same as the
 target vector, but with all elements which correspond to zeros in the
 mask vector deleted.  Thus, for example, ‘vmask([1, 0, 1, 0, 1], [a, b,
 c, d, e])’ produces ‘[a, c, e]’.  SeeLogical Operations.
 
    The ‘v e’ (‘calc-expand-vector’) [‘vexp’] command expands a vector
 according to another mask vector.  The result is a vector the same
 length as the mask, but with nonzero elements replaced by successive
 elements from the target vector.  The length of the target vector is
 normally the number of nonzero elements in the mask.  If the target
 vector is longer, its last few elements are lost.  If the target vector
 is shorter, the last few nonzero mask elements are left unreplaced in
 the result.  Thus ‘vexp([2, 0, 3, 0, 7], [a, b])’ produces ‘[a, 0, b, 0,
 7]’.
 
    With the Hyperbolic flag, ‘H v e’ takes a filler value from the top
 of the stack; the mask and target vectors come from the third and second
 elements of the stack.  This filler is used where the mask is zero:
 ‘vexp([2, 0, 3, 0, 7], [a, b], z)’ produces ‘[a, z, c, z, 7]’.  If the
 filler value is itself a vector, then successive values are taken from
 it, so that the effect is to interleave two vectors according to the
 mask: ‘vexp([2, 0, 3, 7, 0, 0], [a, b], [x, y])’ produces ‘[a, x, b, 7,
 y, 0]’.
 
    Another variation on the masking idea is to combine ‘[a, b, c, d, e]’
 with the mask ‘[1, 0, 1, 0, 1]’ to produce ‘[a, 0, c, 0, e]’.  You can
 accomplish this with ‘V M a &’, mapping the logical “and” operation
 across the two vectors.  SeeLogical Operations.  Note that the ‘?
 :’ operation also discussed there allows other types of masking using
 vectors.