IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
4.3 Creating arrays with values specified ``on-the-fly''


4.3 Creating arrays with values specified ``on-the-fly''

zeros( shape, type)
ones( shape, type)
Often, one needs to manipulate arrays filled with numbers which aren't available beforehand. The numarray module provides a few functions which create arrays from scratch: zeros and ones simply create arrays of a given shape filled with zeros and ones respectively:
>>> z = zeros((3,3))
>>> print z
[[0 0 0]
 [0 0 0]
 [0 0 0]]
>>> o = ones([2,3])
>>> print o
[[1 1 1]
 [1 1 1]]
Note that the first argument is a shape -- it needs to be a tuple or a list of integers. Also note that the default type for the returned arrays is Int, which you can override, e. g.:
>>> o = ones((2,3), Float32)
>>> print o
[[ 1.  1.  1.]
 [ 1.  1.  1.]]

arrayrange( a1, a2=None, stride=1, type=None, shape=None)
arange( a1, a2=None, stride=1, type=None, shape=None)
The arange function is similar to the range function in Python, except that it returns an array as opposed to a list. arange and arrayrange are equivalent.
>>> r = arange(10)
>>> print r
[0 1 2 3 4 5 6 7 8 9]
Combining the arange with the reshape function, we can get:
>>> big = reshape(arange(100),(10,10))
>>> print big
[[ 0  1  2  3  4  5  6  7  8  9]
 [10 11 12 13 14 15 16 17 18 19]
 [20 21 22 23 24 25 26 27 28 29]
 [30 31 32 33 34 35 36 37 38 39]
 [40 41 42 43 44 45 46 47 48 49]
 [50 51 52 53 54 55 56 57 58 59]
 [60 61 62 63 64 65 66 67 68 69]
 [70 71 72 73 74 75 76 77 78 79]
 [80 81 82 83 84 85 86 87 88 89]
 [90 91 92 93 94 95 96 97 98 99]]
One can set the a1, a2, and stride arguments, which allows for more varied ranges:
>>> print arange(10,-10,-2)
[10  8  6  4  2  0  -2  -4  -6  -8]
An important feature of arange is that it can be used with non-integer starting points and strides:
>>> print arange(5.0)
[ 0. 1. 2. 3. 4.]
>>> print arange(0, 1, .2)
[ 0.   0.2  0.4  0.6  0.8]
If you want to create an array with just one value, repeated over and over, you can use the * operator applied to lists
>>> a = array([[3]*5]*5)
>>> print a
[[3 3 3 3 3]
 [3 3 3 3 3]
 [3 3 3 3 3]
 [3 3 3 3 3]
 [3 3 3 3 3]]
but that is relatively slow, since the duplication is done on Python lists. A quicker way would be to start with 0's and add 3:
         >>> a = zeros([5,5]) + 3
         >>> print a
         [[3 3 3 3 3]
          [3 3 3 3 3]
          [3 3 3 3 3]
          [3 3 3 3 3]
          [3 3 3 3 3]]
The optional type argument forces the type of the resulting array, which is otherwise the ``highest'' of the a1, a2, and stride arguments. The a1 argument defaults to 0 if not specified. Note that if the specified type is is ``lower'' than what arange would normally use, the array is the result of a precision-losing cast (a round-down, as that used in the astype method for arrays.)


4.3.1 Creating an array from a function

fromfunction( object, shape)
Finally, one may want to create an array whose elements are the result of a function evaluation. This is done using the fromfunction function, which takes two arguments, a shape and a callable object (usually a function). For example:
>>> def dist(x,y):
...   return (x-5)**2+(y-5)**2          # distance from (5,5) squared
...
>>> m = fromfunction(dist, (10,10))
>>> print m
[[50 41 34 29 26 25 26 29 34 41]
 [41 32 25 20 17 16 17 20 25 32]
 [34 25 18 13 10  9 10 13 18 25]
 [29 20 13  8  5  4  5  8 13 20]
 [26 17 10  5  2  1  2  5 10 17]
 [25 16  9  4  1  0  1  4  9 16]
 [26 17 10  5  2  1  2  5 10 17]
 [29 20 13  8  5  4  5  8 13 20]
 [34 25 18 13 10  9 10 13 18 25]
 [41 32 25 20 17 16 17 20 25 32]]
>>> m = fromfunction(lambda i,j,k: 100*(i+1)+10*(j+1)+(k+1), (4,2,3))
>>> print m
[[[111 112 113]
  [121 122 123]]
 [[211 212 213]
  [221 222 223]]
 [[311 312 313]
  [321 322 323]]
 [[411 412 413]
  [421 422 423]]]
These examples show that fromfunction creates an array of the shape specified by its second argument, and with the contents corresponding to the value of the function argument (the first argument) evaluated at the indices of the array. Thus the value of m[3, 4] in the first example above is the value of dist when x=3 and y=4. Similarly for the lambda function in the second example, but with a rank-3 array. The implementation of fromfunction consists of:
def fromfunction(function, dimensions):
    return apply(function, tuple(indices(dimensions)))
which means that the function function is called with arguments given by the sequence indices(dimensions). As described in the definition of indices, this consists of arrays of indices which will be of rank one less than that specified by dimensions. This means that the function argument must accept the same number of arguments as there are dimensions in dimensions, and that each argument will be an array of the same shape as that specified by dimensions. Furthermore, the array which is passed as the first argument corresponds to the indices of each element in the resulting array along the first axis, that which is passed as the second argument corresponds to the indices of each element in the resulting array along the second axis, etc. A consequence of this is that the function which is used with fromfunction will work as expected only if it performs a separable computation on its arguments, and expects its arguments to be indices along each axis. Thus, no logical operation on the arguments can be performed, or any non-shape preserving operation. Thus, the following will not work as expected:
>>> def buggy(test):
...     if test > 4: return 1
...     else: return 0
...
>>> print fromfunction(buggy,(10,))
Traceback (most recent call last):
...
RuntimeError: An array doesn't make sense as a truth value.  Use any(a) or
all(a).
The reason buggy() failed is that indices((10,)) results in an array passed as test. The result of comparing test with 4 is also an array which has no unambiguous meaning as a truth value.

Here is how to do it properly. We add a print statement to the function for clarity:

>>> def notbuggy(test):                 # only works in Python 2.1 & later
...     print test
...     return where(test>4,1,0)
...
>>> fromfunction(notbuggy,(10,))
[0 1 2 3 4 5 6 7 8 9]
array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1])
We leave it as an excercise for the reader to figure out why the ``buggy'' example gave the result 1.

identity( size)
The identity function takes a single integer argument and returns a square identity array (in the ``matrix'' sense) of that size of integers:
      >>> print identity(5)
      [[1 0 0 0 0]
       [0 1 0 0 0]
       [0 0 1 0 0]
       [0 0 0 1 0]
       [0 0 0 0 1]]

Send comments to the NumArray community.