# Guide to NumPy Array Reshaping

The NumPy library in Python provides robust functionality for reshaping the dimensions of an array, which is what we’ll explore in-depth in this tutorial.

Throughout the tutorial, we’ll cover what NumPy array reshaping is and its importance, before delving into the specifics of how to reshape arrays of varying dimensions.

By the end of this tutorial, you will be proficient in reshaping NumPy arrays and understanding how these techniques can be applied to real-world data manipulation tasks.

## Why is Reshape Functionality Crucial?

Reshaping arrays in NumPy is a critical operation, especially in the field of data science and machine learning.

It allows you to restructure your data to suit different algorithms that might require inputs in specific dimensions or shapes. Notably, the reshape function doesn’t change the original data of the array, ensuring data integrity.
For example, certain machine learning models may require inputs to be in a 2-d array, even if there is only one feature.

In such cases, reshaping allows you to transform your 1-d array into a 2-d array.

It typically returns a view on the original array, which means it does not duplicate the data but instead provides a new way of indexing it.

This allows you to work with large datasets effectively without worrying about memory usage.

## The numpy.reshape() function

The `reshape()` function in NumPy is used to change the shape of an array. It takes as its first argument the new shape you want to specify for the array, which should be compatible with the original array’s shape.

This means the total number of elements in the original array should be the same as the total number of elements in the reshaped array.
Here is a simple example:

```import numpy as np

# original array
arr = np.array([0, 1, 2, 3, 4, 5])
print("Original Array: ", arr)

# reshaping the array
reshaped_arr = np.reshape(arr, (3, 2))
print("Reshaped Array: \n", reshaped_arr)
```

Output:

```Original Array:  [0 1 2 3 4 5]
Reshaped Array:
[[0 1]
[2 3]
[4 5]]
```

In the above example, we used the `np.reshape` method to change the shape of the 1-d array `arr` to a 2-d array.

The new array, `reshaped_arr`, is a 2-d array of shape (3, 2), meaning it has 3 rows and 2 columns. The `np.reshape` method took as its first argument the array to reshape, and as its second argument, the new shape.
The reshaped array still references the same data in memory as the original array, meaning that changes to the original array will be reflected in the reshaped array and vice versa.

## NumPy Reshape Order (Index Order)

When reshaping arrays, NumPy offers flexibility in the form of different orders, or ways to rearrange the elements. The ‘C’, ‘F’, and ‘A’ orders are most commonly used.

• ‘C’ order, or C-style order, means that operating row-rise in the style of the C language.
• ‘F’ order, or Fortran-style order, means that operation is column-wise.
•  ‘A’ order, also known as preserve order, means if the array is Fortran contiguous in memory, then use ‘F’, otherwise use ‘C’.

Here’s how they work:

```import numpy as np

# original array
arr = np.array([[1, 2, 3], [4, 5, 6]])
print("Original Array: \n", arr)

# using reshape with C order
reshaped_c_arr = np.reshape(arr, (3, 2), order='C')
print("Reshaped Array in C order: \n", reshaped_c_arr)

# using reshape with F order
reshaped_f_arr = np.reshape(arr, (3, 2), order='F')
print("Reshaped Array in F order: \n", reshaped_f_arr)

# Using reshape with A order
reshaped_a_arr = arr.reshape(3, 2, order='A')
print("Reshaped Array in A order: \n", reshaped_a_arr)
```

Output:

```Original Array:
[[1 2 3]
[4 5 6]]
Reshaped Array in C order:
[[1 2]
[3 4]
[5 6]]
Reshaped Array in F order:
[[1 3]
[5 2]
[4 6]]
Reshaped Array in A order:
[[1 2]
[3 4]
[5 6]]
```

In this example, the original 2-d array `arr` is reshaped into a 3×2 array using both C and F orders. When reshaping in C order (`reshaped_c_arr`), the array is read row-wise, just like you would read English text from left to right, then top to bottom.

On the other hand, when reshaping in F order (`reshaped_f_arr`), the array is read column-wise, going down the first column and then proceeding to the next.

Specifying the order parameter in the reshape function allows you to decide the logic by which elements are taken from the original array and arranged in the new array.

## Using numpy.ndarray.reshape()

The `numpy.ndarray.reshape()` method is an instance method that behaves similarly to the `numpy.reshape()` function.
Let’s see how it works:

```import numpy as np

# original array
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
print("Original Array: ", arr)

# reshaped array
reshaped_arr = arr.reshape(2, 4)
print("Reshaped Array: \n", reshaped_arr)
```

Output:

```Original Array:  [1 2 3 4 5 6 7 8]
Reshaped Array:
[[1 2 3 4]
[5 6 7 8]]
```

Here, the original 1d array `arr` is reshaped into a 2-d array `reshaped_arr` by using the ndarray’s reshape method.

The reshaped array `reshaped_arr` now has two rows and four columns. The new shape (2, 4) was passed directly to the reshape method without needing to be enclosed in a tuple, which is allowed when reshaping using the ndarray’s reshape method.

## numpy.ndarray.reshape() vs. numpy.reshape()

Their functionality is essentially the same, but their usage slightly differs.

The `numpy.ndarray.reshape` is a method of the ndarray class, meaning it’s a function that every ndarray object has and can use. Instead of being a standalone function, it’s called on an array object. Here’s an example:

```import numpy as np
a = np.array([1, 2, 3, 4, 5, 6])
b = a.reshape((2, 3))```

So, the difference between them is really just in how you call them.

`numpy.reshape` is called as a function that takes an array as an argument, and `numpy.ndarray.reshape` is called as a method on an array object.

## Reshaping 1-Dimensional to 2-D Arrays

You can reshape a 1-d array to a 2-d array using the reshape method. Here’s how you can do it:

```import numpy as np

# original 1d array
arr_1d = np.array([1, 2, 3, 4, 5, 6])
print("Original 1d Array: ", arr_1d)

# reshaping to 2d array
arr_2d = arr_1d.reshape((3, 2))
print("Reshaped 2d Array: \n", arr_2d)
```

Output:

```Original 1d Array:  [1 2 3 4 5 6]
Reshaped 2d Array:
[[1 2]
[3 4]
[5 6]]
```

Here, we’ve converted the 1d array, `arr_1d`, into a 2d array, `arr_2d`, by using the reshape method.

We pass a tuple `(3, 2)` as an argument to the reshape method, indicating that we want to convert the array into a 2-d array with 3 rows and 2 columns. The resulting array, `arr_2d`, reflects the new shape.

## Reshaping 2-D to 3-D Arrays

Let’s now take a look at reshaping a 2-d array into a 3-d array. This can be quite useful when dealing with more complex data, such as images or multi-variate time-series data.

```import numpy as np

# original 2d array
arr_2d = np.array([[1, 2, 3], [4, 5, 6]])
print("Original 2d Array: \n", arr_2d)

# reshaping to 3d array
arr_3d = arr_2d.reshape((2, 1, 3))
print("Reshaped 3d Array: \n", arr_3d)
```

Output:

```Original 2d Array:
[[1 2 3]
[4 5 6]]
Reshaped 3d Array:
[[[1 2 3]]
[[4 5 6]]]
```

In this example, we’ve reshaped a 2-d array, `arr_2d`, into a 3-d array, `arr_3d`. We passed a tuple `(2, 1, 3)` to the reshape method, which indicates we want to convert the array into a 3-d array with 2 elements in the first dimension, 1 element in the second dimension, and 3 elements in the third dimension. This results in a 3d array, `arr_3d`.

## Reshaping 1-D to Multi-Dimensional Arrays

It’s also possible to reshape a 1-d array to a multi-dimensional array. For instance, a 1-d array can be reshaped into a 3-d array, as shown in the following example:

```import numpy as np

# original 1d array
arr_1d = np.array([1, 2, 3, 4, 5, 6])
print("Original 1d Array: ", arr_1d)

# reshaping to 3d array
arr_3d = arr_1d.reshape((2, 1, 3))
print("Reshaped 3d Array: \n", arr_3d)
```

Output:

```Original 1d Array:  [1 2 3 4 5 6]
Reshaped 3d Array:
[[[1 2 3]]
[[4 5 6]]]
```

In the above example, the 1-d array `arr_1d` is reshaped into a 3-d array `arr_3d`. The reshape method takes a tuple `(2, 1, 3)` specifying the desired shape of the new array.

The reshaped array `arr_3d` now has two blocks, each containing a single row of three elements.

## Reshaping with -1 (Unknown dimensions)

When reshaping an array, you can use `-1` in the new shape that you specify, which lets NumPy automatically calculate the size of the dimension for that `-1`.

This is handy when you know the shape of some dimensions and want NumPy to figure out the remaining dimension.
Here’s an example:

```import numpy as np

# original 1d array
arr_1d = np.array([1, 2, 3, 4, 5, 6])
print("Original 1d Array: ", arr_1d)

# reshaping with -1
arr_2d = arr_1d.reshape((3, -1))
print("Reshaped 2d Array: \n", arr_2d)
```

Output:

```Original 1d Array:  [1 2 3 4 5 6]
Reshaped 2d Array:
[[1 2]
[3 4]
[5 6]]
```

In this case, the original array `arr_1d` is reshaped into a 2-d array `arr_2d` using `-1`. When passing the tuple `(3, -1)` to the reshape method, we specify that we want the new array to have three rows, and let NumPy calculate the number of columns needed (in this case, 2) to preserve the number of elements in the original array.

## Reshaping 4-D to 2-D Arrays

Reshaping from 4-Dimensional arrays to 2-Dimensional is also quite common, particularly when working with image data, where we often deal with batches of multiple images.

```import numpy as np

# Create a 4-D array of shape (2, 2, 3, 3)
arr_4d = np.random.randint(10, size=(2, 2, 3, 3))
print("Original 4-D Array: \n", arr_4d)

# Reshape 4-D array to 2-D array
arr_2d = arr_4d.reshape(-1, arr_4d.shape[-1])
print("\nReshaped 2-D Array: \n", arr_2d)
```

Output:

```Original 4-D Array:
[[[[8 2 9]
[8 6 5]
[7 8 0]]

[[6 0 0]
[5 2 4]
[2 1 9]]]

[[[4 9 2]
[4 5 1]
[2 3 9]]

[[2 3 3]
[6 9 1]
[8 1 3]]]]

Reshaped 2-D Array:
[[8 2 9]
[8 6 5]
[7 8 0]
[6 0 0]
[5 2 4]
[2 1 9]
[4 9 2]
[4 5 1]
[2 3 9]
[2 3 3]
[6 9 1]
[8 1 3]]
```

The original array had the shape (2, 2, 3, 3), and we wanted to reshape it into a 2-D array with the last dimension kept intact.

Thus, we used `-1` for the new shape’s first dimension, and `arr_4d.shape[-1]` for the second dimension.

The result is a 2-D array where the first dimension was inferred by NumPy, and the second dimension was the same as the original array’s last dimension.

## Real-World Examples of NumPy Array Reshaping

NumPy array reshaping is a fundamental operation in data processing and machine learning. For example:

• Image processing: Images loaded in Python become NumPy arrays and often require reshaping. For example, a colored image of shape (width, height, 3) might need to be reshaped to a 1-d array before being fed into a neural network for training.
• Neural Networks: The input layer of a neural network often requires data in a specific shape. Thus, reshaping allows the feeding of data in batches of a certain size.

Here’s a simple example of reshaping in image processing:

```from PIL import Image
import numpy as np
img = Image.open('image.jpg')

# Convert image to a NumPy array
img_arr = np.array(img)
print("Original Image Shape: ", img_arr.shape)

# Reshape the image array
reshaped_img_arr = np.reshape(img_arr, -1)
print("Reshaped Image Array Shape: ", reshaped_img_arr.shape)
```

Output:

```Original Image Shape: (800, 800, 3)
Reshaped Image Array Shape: (1920000,)```

In this example, we’ve opened an image using the PIL library and converted it into a NumPy array `img_arr`.

The original shape of `img_arr` would be (height, width, channels), where channels represent the RGB values.

The image array is then reshaped using the `numpy.reshape()` function to a 1-d array `reshaped_img_arr`, which could then be used as input to a machine learning algorithm.

## F.A.Q

Q: How can I reshape a 1-d numpy array to a 2-d array?

A: You can convert a 1-d array to a 2-d array using the numpy reshape() function. This function is used to change the shape of the array without changing its data.

For example, if you have an array of 8 elements, you can use reshape(2,4) to convert it into a 2-dimension array with two rows and four columns.

Q: What is the role of the array shape parameter in the numpy reshape() function?

A: The array shape parameter in the numpy reshape function specifies the new shape you want to reshape the array into.

Specifically, it’s a tuple indicating the number of elements in each dimension for the new array. The total number of elements in the new shape should be compatible with the original shape.

Q: How can I use numpy reshape to convert a 2-d array to a 1-d array?

A: You can convert a 2-d array to a 1-d numpy array using the reshape() function with -1 as the new shape parameter.

This tells NumPy to calculate the size of the dimension as big as necessary to accommodate all the elements of the array based on the original array size.

Q: What do C-like and Fortran-like index orders mean when reshaping a NumPy array?

A: C-like (‘C’ order or, named after the C programming language) means that the array is reshaped row-wise. This is also known as row-major order. This is the default ordering in NumPy.

Fortran-like (‘F’ order or, named after the Fortran programming language) means that the array is reshaped column-wise. You indicate these options in numpy reshape using the order parameter.

Q: Can I add or remove dimensions with numpy reshape?

A: Yes, you can add or remove dimensions of the array using numpy reshape. For example, you can convert a 3D array to a 2D array (removing a dimension).

Q: I have a 3-d array and I want to convert it to a 2-d array. What should I consider?

A: When converting a 3-d array to a 2-d array using numpy reshape, you need to make sure that the total number of elements in the 2-d array will be the same as in the 3-d array. For example, if you have a 3-d numpy array with shape (2, 3, 4), you could reshape it to a 2-d array with shape (6, 4).

Q: How does array indexing work when reshaping an ndarray?

A: Array indexing works based on the shape of the ndarray. When you use reshape to change the shape of a NumPy array, the original data in the array is realigned according to the new shape, but the mapping between the elements and their indices in the array is preserved. This is done according to either the ‘C’ or Fortran’ memory layout, depending on what you specify.

Q: What does it mean when we say the new shape is “compatible with the original shape”?

A: When we reshape a NumPy array, the compatible with the original shape means that the new shape’s total number of elements matches the total number of elements in the original array.

For instance, if you have an array with 8 elements, it is compatible with any other shape that also has 8 elements (such as (2,4), (4,2), or (8,1)).

Q: In the reshape NumPy array they mentioned the use of reshape(-1, 1). What does that do?

A: The reshape(-1, 1) in NumPy is used to convert the array to a 2D numpy array with one column and as many rows as necessary.

The -1 is a special value that tells NumPy to compute the size of the dimension as big as necessary to accommodate all the elements of the array.