29.numpy 2
NumPy Array Copy vs View
The main difference between a copy and a view of an array is that the copy is a new array, and the view is just a view of the original array.
The copy owns the data and any changes made to the copy will not affect original array, and any changes made to the original array will not affect the copy.
The view does not own the data and any changes made to the view will affect the original array, and any changes made to the original array will affect the view.
Copy
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
x = arr.copy()
arr[0] = 42
print(arr)
>>> [42 2 3 4 5]
print(x)
>>> [1 2 3 4 5]
The copy SHOULD NOT be affected by the changes made to the original array.
View
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
x = arr.view()
arr[0] = 42
print(arr)
>>> [42 2 3 4 5]
print(x)
>>> [42 2 3 4 5]
The view SHOULD be affected by the changes made to the original array.
The original array SHOULD be affected by the changes made to the view.
Check if Array Owns it's Data
As mentioned above, copies owns the data, and views does not own the data, but how can we check this?
Every NumPy array has the attribute base that returns None if the array owns the data.
Otherwise, the base attribute refers to the original object.
Example
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
x = arr.copy()
y = arr.view()
print(x.base)
>>> None
print(y.base)
>>> [1 2 3 4 5]
NumPy Array Shape
The shape of an array is the number of elements in each dimension.
NumPy arrays have an attribute called shape that returns a tuple with each index having the number of corresponding elements.
2-D Array
import numpy as np
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
print(arr.shape)
>>> (2,4)
5-D Array
import numpy as np
arr = np.array([1, 2, 3, 4], ndmin=5)
print(arr)
>>> [[[[[1 2 3 4]]]]]
print(arr.shape)
>>> (1, 1, 1, 1, 4)
NumPy Array Reshaping
Reshaping means changing the shape of an array.
The shape of an array is the number of elements in each dimension.
By reshaping we can add or remove dimensions or change number of elements in each dimension.
Reshape from 1-D to 2-D
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
newarr = arr.reshape(4, 3)
print(newarr)
>>> [[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
Reshape from 1-D to 3-D
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
newarr = arr.reshape(2, 3, 2)
print(newarr)
>>> [[[ 1 2]
[ 3 4]
[ 5 6]]
[[ 7 8]
[ 9 10]
[11 12]]]
Note
"We can reshape the array into any shape as long as the elements required for reshaping are equal in both shapes."
Returns Copy or View?
Example
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
print(arr.reshape(2, 4).base)
>>> [1 2 3 4 5 6 7 8]
The example above returns the original array, so it is a view.
Unknown Dimension
We are allowed to have one "unknown" dimension.
Meaning that we do not have to specify an exact number for one of the dimensions in the reshape method.
Pass -1 as the value, and NumPy will calculate this number.
Example
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
newarr = arr.reshape(2, -1)
print(newarr)
>>> [[[1 2]
[3 4]]
[[5 6]
[7 8]]]
We can not pass -1 to more than one dimension.
Flattening the arrays
Flattening array means converting a multidimensional array into a 1D array.
We can use reshape(-1) to do this.
Example
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
newarr = arr.reshape(-1)
print(newarr)
>>> [1 2 3 4 5 6]
NumPy Array Iterating
In basic for loops, iterating through each scalar of an array we need to use n for loops which can be difficult to write for arrays with very high dimensionality.
Iterating Arrays Using nditer()
The function nditer()
is a helping function that can be used from very basic to very advanced iterations.
Iterating on Each Scalar Element
Example
import numpy as np
arr = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
for x in np.nditer(arr):
print(x)
>>> 1
2
3
4
5
6
7
8
Iterating With Different Step Size
Example
import numpy as np
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
for x in np.nditer(arr[:, ::2]):
print(x)
>>> 1
3
5
7
Enumerated Iteration Using ndenumerate()
Enumeration means mentioning sequence number of somethings one by one.
Sometimes we require corresponding index of the element while iterating, the ndenumerate()
method can be used for those usecases.
For 1-D Array
import numpy as np
arr = np.array([1, 2, 3])
for idx, x in np.ndenumerate(arr):
print(idx, x)
>>> (0,) 1
(1,) 2
(2,) 3
For 2-D Array
import numpy as np
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
for idx, x in np.ndenumerate(arr):
print(idx, x)
>>> (0, 0) 1
(0, 1) 2
(0, 2) 3
(0, 3) 4
(1, 0) 5
(1, 1) 6
(1, 2) 7
(1, 3) 8
NumPy Joining Array
Joining means putting contents of two or more arrays in a single array.
In SQL we join tables based on a key, whereas in NumPy we join arrays by axes.
We pass a sequence of arrays that we want to join to the concatenate()
function, along with the axis. If axis is not explicitly passed, it is taken as 0.
(axis-0 represents rows and axis-1 represents columns)
Join two 1-D Arrays
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
arr = np.concatenate((arr1, arr2))
print(arr)
>>> [1,2,3,4,5,6]
Join two 2-D Arrays
import numpy as np
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
arr = np.concatenate((arr1, arr2), axis=1)
print(arr)
>>> [[1 2 5 6]
[3 4 7 8]]
Joining Arrays Using Stack Functions
Stacking is same as concatenation, the only difference is that stacking is done along a new axis.
We can concatenate two 1-D arrays along the second axis which would result in putting them one over the other, ie. stacking.
We pass a sequence of arrays that we want to join to the concatenate() method along with the axis. If axis is not explicitly passed it is taken as 0.
Example
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
arr = np.stack((arr1, arr2), axis=1)
print(arr)
>>> [[1 4]
[2 5]
[3 6]]
Row Wise Stacking
hstack()
to stack along rows.
Example
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
arr = np.hstack((arr1, arr2))
print(arr)
>>> [1,2,3,4,5,6]
Column Wise stacking
vstack()
to stack along columns.
Example
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
arr = np.vstack((arr1, arr2))
print(arr)
>>> [[1 2 3]
[4 5 6]]