NumPy Array Manipulation. A practical guide to modify the shape... | by Soner Yıldırım | Towards Data Science

Everything about data science starts with data and it comes in various formats. Numbers, images, texts, x-rays, sound and video recordings are just some examples of data sources. Whatever the format data comes in, it needs to be converted to an array of numbers to be analyzed. Complex computer vision models cannot see or process an image like a human being. An image is converted to an array of numbers before analyzed. Hence, it is crucial to effectively store and modify arrays of numbers in data science.NumPy (Numerical Python) is a scientific computing package that offers very functional ways to create and operate on arrays of numbers.
In this post, I will cover the ways to manipulate the shape of an array in NumPy using the following operations:
Reshape
Expand_dims
Ravel and Flatten
If you would like to read about the basics of NumPy, you can visit the following post:
towardsdatascience.com
Let’s start with importing NumPy:
import numpy as np
Tip: NumPy arrays are much more efficient than lists in terms of storage and processing.
Numpy provides flexible tools to change the dimension of an array. Before changing the dimension, it is better to remember what dimension of an array means and how arrays with different dimension look like:
a = np.random.randint(10, size=5)aarray([9, 7, 3, 7, 5])a.ndim1a.shape(5,0)
We can also create multidimensional arrays with numpy:
# 2-dimensionalb = np.zeros((3,4))barray([[0., 0., 0., 0.],               [0., 0., 0., 0.],               [0., 0., 0., 0.]])b.ndim2# 3-dimensionalc = np.ones((2,2,2))carray([[[1., 1.],                 [1., 1.]],                 [[1., 1.],                  [1., 1.]]])c.ndim3
There are different ways to change the dimension of an array. Reshape function is commonly used to modify the shape and thus the dimension of an array. We just need to pass the new shape as an argument to reshape function:
Tip: I use different ways when creating arrays for examples so that you will also get familiar with creating arrays.
np.arange(6)array([0, 1, 2, 3, 4, 5])np.arange(6).reshape(2,3)array([[0, 1, 2],               [3, 4, 5]])
Reshape (2,3) returns a new array with 2 rows and 3 columns which is 2-dimensional. So the array that we apply reshape(2,3) must be 6 elements.
Let’s also create a 3-dimensional array using reshape:
np.arange(8).reshape(2,2,2)array([[[0, 1],                 [2, 3]],                 [[4, 5],                  [6, 7]]])
One very useful feature of reshape function is that if you do not know the number of elements in the original array, you can specify one of the dimensions as “-1”.
Since we almost always work with very large arrays, it is also convenient to type (-1,1) instead of (100000,1).
Tip: When reshaping arrays, the new shape needs to be compatible with the original shape.
np.arange(6).reshape(-1,2)array([[0, 1],               [2, 3],               [4, 5]])np.arange(6).reshape(-1,3)array([[0, 1, 2],               [3, 4, 5]])
It is also possible to increase the dimension without changing the sequence of elements. We can achieve it by reshape(-1,1) or (1,-1):
np.random.normal(0,1,3)array([-0.14788456,  0.01909406,  0.88659889])np.random.normal(0,1,3).reshape(-1,1)array([[-0.14588167],               [ 0.06871804],               [ 2.32699261]])np.random.normal(0,1,3).reshape(1,-1)array([[ 1.46812451,  0.48818206, -0.80228877]])
As the name suggests, expand_dims expands the shape of an array.
a = np.array([1,2,3])np.expand_dims(a, axis=0)array([[1, 2, 3]])np.expand_dims(a, axis=1)array([[1],               [2],               [3]])
axis parameter allows to choose through which axis the expansion is done.
expand_dims with axis=1 is equivalent to reshape(-1,1).
np.expand_dims(a, axis=1)array([[1],               [2],               [3]])np.expand_dims(a, axis=1)array([[1],               [2],               [3]])
Ravel returns a flattened array. If you are familiar with convolutional neural netwoks (CNN), pooled feature maps are flattened before feeding to fully connected layer. This operation is converting a 2-D array to a 1-D array.
a = np.random.randint(10, size=(2,3))aarray([[6, 8, 2],               [5, 1, 8]])np.ravel(a)array([6, 8, 2, 5, 1, 8])
Second row is concatenated at the end of first row. Ravel function also allows to column-wise concatenation using order parameter:
np.ravel(a, order='F')array([6, 5, 8, 1, 2, 8])
Flatten also performs the same operation:
array([[3, 5, 2],               [6, 7, 8]])a.flatten()array([3, 5, 2, 6, 7, 8])
The difference between ravel and flatten:
Ravel: Returns a view of the original array when possible.
Flatten: Always returns a copy of the original array.
Therefore, the changes you make on an array return by flatten will never be made on the original array. However, if you modify the returned array by ravel, you may also change the original array. Let’s go over an example to make it clear:
array([[3, 5, 2],               [6, 7, 8]])a.flatten()[0] = 10aarray([[3, 5, 2],               [6, 7, 8]])np.ravel(a)[0] = 10aarray([[10,  5,  2],               [ 6,  7,  8]])
As you can see, the changes we make on ravel also changed the original array.
Thank you for reading. Please let me know if you have any feedback.