Python Lesson 19: NumPy Array Shaping (NumPy pt.2)

Hello everybody,

Michael here, and today’s post will on how to manipulate the shape of arrays in NumPy-this is the second lesson in my NumPy series.

Now, before we get started, let’s remember to import NumPy to our IDE using the line import numpy as np.

  • Remember to pip install numpy if you haven’t done so already! Also, if you’re not sure if you’ve already got NumPy, use the pip list command to check.

Now that the import has been taken care of, let’s first demonstrate how to find the shape of a NumPy array:

arrayA = np.array([[0.5, 1, 1.5, 2, 2.5, 3], [3.5, 4, 4.5, 5, 5.5, 6]])
print(arrayA.shape)

(2, 6)

In this example, I created a 2-D array with six elements in each array. To find out the array’s shape, I called the array’s .shape function. The shape is shown as (2, 6), which means that this array has 2 dimensions and 6 elements per dimension.

Now how would we reshape this array? Let’s say that we wanted to turn this 2-D array into a 3-D array. Here’s how we would do that:

arrayB = arrayA.reshape(3, 4)
print(arrayB.shape)
print(arrayB)

(3, 4)
[[0.5 1.  1.5 2. ]
 [2.5 3.  3.5 4. ]
 [4.5 5.  5.5 6. ]]

To reshape a NumPy array, use the .reshape function on your current array and change the parameters of the .reshape function to the dimensions you want the new array to have.

In this example, I changed the shape of arrayA to 3 X 4, which means that the new array (stored in the arrayB variable) will have 3 dimensions with 4 elements in each dimension.

Look, the .reshape function is quite versatile, but you can just use any two numbers as the parameters here. Here’s what happened when I tried reshaping arrayA to 5×7:

arrayC = arrayA.reshape(5, 7)
print(arrayC)

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-6-70ed58b6935b> in <module>
----> 1 arrayC = arrayA.reshape(5, 7)
      2 print(arrayC)

ValueError: cannot reshape array of size 12 into shape (5,7)

Since 5 and 7 aren’t factors of 12 (the array size), Python couldn’t reshape the array to 5×7.

In order to know all of the possible ways that you can shape the array, count all of the elements in the array (12 in the case of arrayA) then make a note of all of the factors of that amount. Since there are 12 elements in arrayA, the possible shapes arrayA can take include (1, 12), (2, 6), and (3, 4), as these are all number pairs that have a product of 12.

  • (12, 1), (6, 2), and (4, 3) work as well-recall that, from the Commutative Property of Multiplication, you can switch the order of the factors around and get the same product. However, keep in mind that the dimensions will be different if you switch the order of the numbers.
  • Also, when reshaping the array, keep in mind that dimensions are capped at size 32 (I mentioned this in the previous lesson)

Now I’ve demonstrated how to reshape a NumPy array with a standard number-pair tuple. However, did you know that you can also include an unknown dimension. Here’s how that works:

arrayD = np.array([0, 3, 6, 9, 12, 15, 18, 21, 24, 27])

arrayE = arrayD.reshape(2, -1)
print(arrayE)

[[ 0  3  6  9 12]
 [15 18 21 24 27]]

Yes, NumPy allows you to use -1 as a shape parameter in the .reshape method. But what does this mean? -1 simply represents an unknown dimension that you want NumPy to figure out. How does NumPy figure out this unknown dimension? It looks at the length of the array and the known dimension(s) in order to determine how to best shape the array. In this example, NumPy sees that the known dimension is 2, so the array is shaped to have two rows with five elements per row-the array has 10 elements, so 10 divided by 2 (# of rows) equals 5 (# of elements per row).

Now what if I had switched the order of the parameters in the .reshape function to (-1, 2). What would we get?

arrayF = arrayD.reshape(-1, 2)
print(arrayF)

[[ 0  3]
 [ 6  9]
 [12 15]
 [18 21]
 [24 27]]

If I switch the order of the .reshape function parameters to (-1, 2), the array would still have 10 elements but instead of 2 rows-by-5 columns, I get an array with 5 rows-by-2 columns.

As you can see, using the unknown dimension trick of -1 works just great with two shape parameters. However, the -1 trick also works with three shape parameters. Take a look at the example below:

arrayG = arrayD.reshape(2, 5, -1)
print(arrayG)

[[[ 0]
  [ 3]
  [ 6]
  [ 9]
  [12]]

 [[15]
  [18]
  [21]
  [24]
  [27]]]

In this example, using -1 as a third shape parameter splits the array into two 5×1 arrays.

Now what if I still used three shape parameters, but placed the -1 as the second shape parameter?

arrayH = arrayD.reshape(2, -1, 5)
print(arrayH)

[[[ 0  3  6  9 12]]

 [[15 18 21 24 27]]]

In this example, using -1 as the second shape parameter still splits the array in two, except you get two 1×5 arrays.

  • You can only have one unknown dimension in every .reshape function!
  • For all of the known dimensions, you can only include factors of the array length. In other words, since arrayD has a length of 10, you could only use 1, 2, 5, or 10 for the known dimension(s), as these are all the factors of 10.

The next NumPy trick I will show you is how to flatten arrays. In NumPy, you can convert multi-dimensional arrays into 1-D arrays-this is called flattening the array-with a simple line of code. Here’s how to flatten a NumPy array:

arrayI = np.array([[4, 8, 12], [5, 10, 15], [6, 12, 18]])
arrayJ = arrayI.reshape(-1)
print(arrayJ)

[ 4  8 12  5 10 15  6 12 18]

To flatten a NumPy array, simply use the .reshape function with the -1 parameter. That’s it. However, for the flattening to work, only use the -1 shape parameter-don’t include other shape parameters!

Now I know I said that the array-flattening trick works with multi-dimensional arrays, but it also works with 0-D arrays. Here’s an example of this:

arrayK = np.array(7)
arrayL = arrayK.reshape(-1)
print(arrayL)

[7]

As you can see, my 0-D was successfully turned into a 1-D array.

Last but not least, I want to show you two special NumPy functions that you will likely encounter if you’re learning about more advanced Python topics (e.g. computer vision)-.zeros and .ones. These functions allow you to create arrays of zeros and ones, respectively (recall that 0 and 1 are the two elements in the binary number system from Java Lesson 5: Java Numbering Systems).

First, let’s create an array of zeros:

arrayM = np.zeros((4,4), int)
print(arrayM)

[[0 0 0 0]
 [0 0 0 0]
 [0 0 0 0]
 [0 0 0 0]]

In this .zeros function, I used two parameters-a tuple to specify the shape of the array (4×4) and a value to specify the type to store the zeros (int).

Let’s say I didn’t specify a value type for the zeros. How would they be stored on the program?

arrayM = np.zeros((4,4))
print(arrayM)
print(arrayM.dtype)

[[0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]]
float64

In this example, I didn’t set a value type for the zeros, so they are by default stored as type float64-which is a 64-bit floating point number.

  • If you want to check the type of all the values used in the NumPy array, use the .dtype function, not .type.
  • The number of shape parameters you use for the shape tuple in the .zeros and .ones functions indicates the number of dimensions your array will have. In the example above, I used two shape parameters for the shape tuple, therefore my array has two dimensions.

Now let’s create an array of ones:

arrayN = np.ones((5,9), int)
print(arrayN)

[[1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1]]

In this example, I created a 5×9 array of ones stored as type int.

Thanks for reading,

Michael

Leave a Reply