 # how to vectorize 3d numpy arrays

• Last Update :
• Techknowledgy :

What is usually done in 3D images is to swap the `Z` axis to the first index:

```>>> a = a.transpose((2, 0, 1)) >>>
a.shape(20, 100, 100)```

And now you can easily iterate over the Z axis:

```>>>
for slice in a:
do something```

Obviously you want to get rid of the explicit `for` loop, but I think whether this is possible depends on what calculation you are doing with C. As a simple example,

```a = np.zeros((100, 100, 20))
a[: ,: ] = np.linspace(1, 20, 20) # example data: 1, 2, 3, .., 20 as "z"
for every "x", "y"

b = np.sum(a[: ,: ] ** 2, axis = 2)```

If your inner calculation is sufficiently complex, and not amenable to vectorization, then your iteration structure is good, and does not contribute significantly to the calculation time

```for (x, y), v in np.ndenumerate(b):
C = a[x, y,: ]
...
for d in range(len(C)):
...# complex, not vectorizable calc
...
b[x, y] = some_value```

It looks like `e` can be calculated for all points at once:

```e = 2.5 * float(math.pow(d_n[x, y] - d, 2)) + C[d] * 0.05

E = 2.5 * (d_n[..., None] - np.arange(a.shape[-1])) ** 2 + a * 0.05 #(100, 100, 20)

E.min(axis = -1) # smallest value along the last dimension
E.argmin(axis = -1) # index of where that min occurs```

Many functions in Numpy are "reduction" functions*, for example `sum`, `any`, `std`, etc. If you supply an `axis` argument other than `None` to such a function it will reduce the dimension of the array over that axis. For your code you can use the `argmin` function, if you first calculate `e` in a vectorized way:

```d = np.arange(a.shape)
e = 2.5 * (d_n[..., None] - d) ** 2 + a * 0.05
b = np.argmin(e, axis = 2)```

The indexing with `[...,None]` is used to engage broadcasting. The values in `e` are floating point values, so it's a bit strange to compare to `sys.maxint` but there you go:

```I, J = np.indices(b.shape)
b[e[I, J, b] >= sys.maxint] = a.shape - 1```

Suggestion : 2

Define a vectorized function which takes a nested sequence of objects or numpy arrays as inputs and returns a single numpy array or a tuple of numpy arrays. The vectorized function evaluates pyfunc over successive tuples of the input arrays like the python map function, except it uses the broadcasting rules of numpy.,The signature argument allows for vectorizing functions that act on non-scalar arrays of fixed length. For example, you can use it for a vectorized calculation of Pearson correlation coefficient and its p-value:,Set of strings or integers representing the positional or keyword arguments for which the function will not be vectorized. These will be passed directly to pyfunc unmodified.,The data type of the output of vectorized is determined by calling the function with the first element of the input. This can be avoided by specifying the otypes argument.

```>>> def myfunc(a, b):
..."Return a-b if a>b, otherwise return a+b"
...
if a > b:
...
return a - b
...
else:
...
return a + b```
```>>> vfunc = np.vectorize(myfunc) >>>
vfunc([1, 2, 3, 4], 2)
array([3, 4, 1, 2])```
```>>> vfunc.__doc__ 'Return a-b if a>b, otherwise return a+b' >>>
vfunc = np.vectorize(myfunc, doc = 'Vectorized `myfunc`') >>>
vfunc.__doc__ 'Vectorized `myfunc`'```
```>>> out = vfunc([1, 2, 3, 4], 2)
>>> type(out)
<class 'numpy.int64'>
>>> vfunc = np.vectorize(myfunc, otypes=[float])
>>> out = vfunc([1, 2, 3, 4], 2)
>>> type(out)
<class 'numpy.float64'>```
```>>> def mypolyval(p, x):
..._p = list(p)
...res = _p.pop(0)
...
while _p:
...res = res * x + _p.pop(0)
...
return res >>>
vpolyval = np.vectorize(mypolyval, excluded = ['p']) >>>
vpolyval(p = [1, 2, 3], x = [0, 1])
array([3, 6])```
```>>> vpolyval.excluded.add(0) >>>
vpolyval([1, 2, 3], x = [0, 1])
array([3, 6])```

Suggestion : 3

Arrays are important because they enable you to express batch operations on data without writing any for loops. This is usually called vectorization. Any arithmetic operations between equal-size arrays applies the operation elementwise:,ndarray, a fast and space-efficient multidimensional array providing vectorized arithmetic operations and sophisticated broadcasting capabilities,Using NumPy arrays enables you to express many kinds of data processing tasks as concise array expressions that might otherwise require writing loops. This practice of replacing explicit loops with array expressions is commonly referred to as vectorization. In general, vectorized array operations will often be one or two (or more) orders of magnitude faster than their pure Python equivalents, with the biggest impact in any kind of numerical computations. Later, in Chapter 12, I will explain broadcasting, a powerful method for vectorizing computations.,The numpy.where function is a vectorized version of the ternary expression x if condition else y. Suppose we had a boolean array and two arrays of values:

```In: data1 = [6, 7.5, 8, 0, 1]

In: arr1 = np.array(data1)

In: arr1
Out: array([6., 7.5, 8., 0., 1.])```
```In: arr1 = np.array([1, 2, 3], dtype = np.float64)

In: arr2 = np.array([1, 2, 3], dtype = np.int32)

In: arr1.dtype In: arr2.dtype
Out: dtype('float64') Out: dtype('int32')```
```In: arr = np.array([
[1., 2., 3.],
[4., 5., 6.]
])

In: arr
Out:
array([
[1., 2., 3.],
[4., 5., 6.]
])

In: arr * arr In: arr - arr
Out: Out:
array([
[1., 4., 9.], array([
[0., 0., 0.],
[16., 25., 36.]
])[0., 0., 0.]
])```
```In: arr = np.arange(10)

In: arr
Out: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In: arr
Out: 5

In: arr[5: 8]
Out: array([5, 6, 7])

In: arr[5: 8] = 12

In: arr
Out: array([0, 1, 2, 3, 4, 12, 12, 12, 8, 9])```
```In: arr[1: 6]
Out: array([1, 2, 3, 4, 64])```
```In: names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])

In: data = np.random.randn(7, 4)

In: names
Out:
array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'],
dtype = '|S4')

In: data
Out:
array([
[-0.048, 0.5433, -0.2349, 1.2792],
[-0.268, 0.5465, 0.0939, -2.0445],
[-0.047, -2.026, 0.7719, 0.3103],
[2.1452, 0.8799, -0.0523, 0.0672],
[-1.0023, -0.1698, 1.1503, 1.7289],
[0.1913, 0.4544, 0.4519, 0.5535],
[0.5994, 0.8174, -0.9297, -1.2564]
])```

Suggestion : 4

Pass -1 as the value, and NumPy will calculate this number for you.,Convert 1D array with 8 elements to 3D array with 2x2 elements:,Try converting 1D array with 8 elements to a 2D array with 3 elements in each dimension (will raise an error):,Convert the following 1-D array with 12 elements into a 3-D array.

```arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])

newarr = arr.(4, 3)```

Suggestion : 5

Introduce the indexing and slicing scheme for accessing a multi-dimensional array’s contents,Thus d3_array[0, 1, 0] specifies the element residing in sheet-0, at row-1 and column-0:,Reading Comprehension: Multi-dimensional Indexing,Let’s begin our discussion by constructing a simple ND-array containing three floating-point numbers.

```# A 0 - D array
np.array(8)

# A 1 - D array, shape - (3, )
np.array([2.3, 0.1, -9.1])

# A 2 - D array, shape - (3, 2)
np.array([
[93, 95],
[84, 100],
[99, 87]
])

# A 3 - D array, shape - (2, 2, 2)
np.array([
[
[0, 1],
[2, 3]
],

[
[4, 5],
[6, 7]
]
])```
```>>>
import numpy as np

# A 3 - D array >>>
x = np.array([
[
[0, 1],
...[2, 3]
],
...
...[
[4, 5],
...[6, 7]
]
])

# get: sheet - 0, both rows, flip order of columns >>>
x[0,: , ::-1]
array([
[1, 0],
[3, 2]
])```
`>>> simple_array = np.array([2.3, 0.1, -9.1])`
```+ -- -- -- + -- -- -- + -- -- -- +
|
2.3 | 0.1 | -9.1 |
+ -- -- -- + -- -- -- + -- -- -- +
0 1 2 -
3 - 2 - 1```
```>>> simple_array
2.3

>>>
simple_array[-2]
0.1

>>>
simple_array[1: 3]
array([0.1, -9.1])

>>>
simple_array
IndexError: index 3 is out of bounds
for axis 0 with size 3```
```# using a 1 - dimensional array to store the grades >>>
grades = np.array([93, 95, 84, 100, 99, 87])```

Suggestion : 6

We can also do this using broadcasting, which is where NumPy implicitly repeats the array without using additional memory. With broadcasting, NumPy takes care of repeating for you, provided dimensions are "compatible". This works as:,We can use this to select all the indices on the other dimensions of our temperature array. We will also need to use the magic of broadcasting to combine arrays of indices across dimensions:,Broadcasting is a useful NumPy tool that allows us to perform operations between arrays with different shapes, provided that they are compatible with each other in certain ways. To start, we can create an array below and add 5 to it:,What if what we really want is pairwise addition of a, b? Without broadcasting, we could accomplish this by looping:

```import numpy as np

a = np.array([10, 20, 30, 40])
a + 5```
`array([15, 25, 35, 45])`
```b = np.array()
a + b```
```b = np.array([5, 6, 7])
a + b```
```b = np.array([5, 5, 10, 10])
a + b```
`array([15, 25, 40, 50])`