Skip to content
2 changes: 1 addition & 1 deletion Python/Module2_EssentialsOfPython/Basic_Objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -1044,7 +1044,7 @@ It is very important to remember this issue of the limited numerical precision o

**Understanding the modulo operator: Solution**

If `n` is an integer, then 2 will divide into it evenly, and thus there is no remainder. If `n` is odd, then `n / 2` must have a remainder of 1. Thus:
If `n` is an even integer, then 2 will divide into it evenly, and thus there is no remainder. If `n` is odd, then `n / 2` must have a remainder of 1. Thus:

- `n % 2 ` = 0 if `n` is an even number
- `n % 2 ` = 1 if `n` is an odd number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ def get_maxes(dictionary):
max_val = max(dictionary.values())
return tuple(k for k,v in dictionary.items() if v == max_val)

>>> get_maxes(dict(a=1, b=2,c= 2, d=1))
>>> get_maxes(dict(a=1, b=2, c=2, d=1))
('b', 'c')
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ Suppose you have an $N$-dimensional array, and only provide $j$ indices for the
</div>
<!-- #endregion -->

Thus far, we have discussed some rules for accessing data in arrays, all of which fall into the category that is designated ["basic indexing"](https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#basic-slicing-and-indexing) by the NumPy documentation. We will discuss the details of basic indexing and of ["advanced indexing"](https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#advanced-indexing), in full, in a later section. Note, however, that all of the indexing/slicing reviewed here produces a "view" of the original array. That is, *no data is copied* when you index into an array using integer indices and/or slices. Recall that slicing lists and tuples *do* produce copies of the data.
Thus far, we have discussed some rules for accessing data in arrays, all of which fall into the category that is designated ["basic indexing"](https://numpy.org/doc/stable/reference/arrays.indexing.html#basic-slicing-and-indexing) by the NumPy documentation. We will discuss the details of basic indexing and of ["advanced indexing"](https://numpy.org/doc/stable/reference/arrays.indexing.html#advanced-indexing), in full, in a later section. Note, however, that all of the indexing/slicing reviewed here produces a "view" of the original array. That is, *no data is copied* when you index into an array using integer indices and/or slices. Recall that slicing lists and tuples *do* produce copies of the data.



Expand Down Expand Up @@ -417,7 +417,7 @@ array([[ 1, 5, 9],
[ 3, 7, 11],
[ 4, 8, 12]])
```
A complete listing of the available array-manipulation functions can be found in the [official NumPy documentation](https://docs.scipy.org/doc/numpy/reference/routines.array-manipulation.html). Among these functions, the reshape function is especially useful.
A complete listing of the available array-manipulation functions can be found in the [official NumPy documentation](https://numpy.org/doc/stable/reference/routines.array-manipulation.html). Among these functions, the reshape function is especially useful.

### Introducing the `reshape` Function
The `reshape` function allows you to change the dimensionality and axis-layout of a given array. This adjusts the indexing interface used to access the array's underlying data, as was discussed in earlier in this module. Let's take a shape-(6,) array, and reshape it to a shape-(2, 3) array:
Expand Down Expand Up @@ -497,10 +497,10 @@ For all straightforward applications of reshape, NumPy does not actually create

## Links to Official Documentation

- [The N-dimensional array](https://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html)
- [Array indexing](https://docs.scipy.org/doc/numpy/user/basics.indexing.html#indexing)
- [Indexing routines](https://docs.scipy.org/doc/numpy/reference/routines.indexing.html#indexing-routines)
- [Array manipulation routines](https://docs.scipy.org/doc/numpy/reference/routines.array-manipulation.html)
- [The N-dimensional array](https://numpy.org/doc/stable/reference/arrays.ndarray.html)
- [Array indexing](https://numpy.org/doc/stable/user/basics.indexing.html#indexing)
- [Indexing routines](https://numpy.org/doc/stable/reference/routines.indexing.html#indexing-routines)
- [Array manipulation routines](https://numpy.org/doc/stable/reference/routines.array-manipulation.html)


## Reading Comprehension Solutions
Expand Down
20 changes: 10 additions & 10 deletions Python/Module3_IntroducingNumpy/AdvancedIndexing.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ False
>>> np.shares_memory(x, x[bool_index])
False
```
The flexibility permitted by advanced indexing makes it a difficult topic to treat exhaustively without delving into somewhat terse and abstract notation. It is best to refer to [the official documentation](https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#advanced-indexing) for such a treatment of the topic. Here, we will discuss the essential aspects of advanced indexing, with the aim of the discussion being both thorough and accessible.
The flexibility permitted by advanced indexing makes it a difficult topic to treat exhaustively without delving into somewhat terse and abstract notation. It is best to refer to [the official documentation](https://numpy.org/doc/stable/reference/arrays.indexing.html#advanced-indexing) for such a treatment of the topic. Here, we will discuss the essential aspects of advanced indexing, with the aim of the discussion being both thorough and accessible.
<!-- #endregion -->

<div class="alert alert-info">
Expand Down Expand Up @@ -392,7 +392,7 @@ Given the following array:
... [-0.29, 0.13, -0.26, 0.33]])
```

Use boolean array-indexing and NumPy's [logical functions](https://docs.scipy.org/doc/numpy/reference/routines.logic.html) to select the contents of `h` that satisfy the following conditions. Because you are dealing with floating-point numbers, [you should not require that two values are exactly equal](https://www.pythonlikeyoumeanit.com/Module2_EssentialsOfPython/Basic_Objects.html#Understanding-Numerical-Precision); rather, make use of the function [numpy.isclose](https://docs.scipy.org/doc/numpy-dev/reference/generated/numpy.isclose.html).
Use boolean array-indexing and NumPy's [logical functions](https://numpy.org/doc/stable/reference/routines.logic.html) to select the contents of `h` that satisfy the following conditions. Because you are dealing with floating-point numbers, [you should not require that two values are exactly equal](https://www.pythonlikeyoumeanit.com/Module2_EssentialsOfPython/Basic_Objects.html#Understanding-Numerical-Precision); rather, make use of the function [numpy.isclose](https://numpy.org/doc/stable/reference/generated/numpy.isclose.html#numpy.isclose).

1. All negative entries in `h`
2. All entries in `h` "equal" to `0.01` or `0.33`
Expand All @@ -403,7 +403,7 @@ Use boolean array-indexing and NumPy's [logical functions](https://docs.scipy.or

<!-- #region -->
### Converting a Boolean Index-Array to Integer Index-Arrays: numpy.where
The function [numpy.where](https://docs.scipy.org/doc/numpy/reference/generated/numpy.where.html) can be used to take a boolean-valued array, and produce the *tuple* of index-arrays that access the `True` entries of that array, via integer array indexing (discussed at the beginning of this section).
The function [numpy.where](https://numpy.org/doc/stable/reference/generated/numpy.where.html) can be used to take a boolean-valued array, and produce the *tuple* of index-arrays that access the `True` entries of that array, via integer array indexing (discussed at the beginning of this section).

```python
# demonstrating `np.where`
Expand Down Expand Up @@ -449,7 +449,7 @@ array([0], dtype=int64)
```
<!-- #endregion -->

Armed with NumPy's suite of [logical functions](https://docs.scipy.org/doc/numpy/reference/routines.logic.html), boolean-array indexing provides a sleek interface for accessing the particular contents of an array, irrespective of the array's shape and the layout of its contents. This method of indexing is especially powerful in the context of performing augmented updates to an array, which is the subject of the following subsection.
Armed with NumPy's suite of [logical functions](https://numpy.org/doc/stable/reference/routines.logic.html), boolean-array indexing provides a sleek interface for accessing the particular contents of an array, irrespective of the array's shape and the layout of its contents. This method of indexing is especially powerful in the context of performing augmented updates to an array, which is the subject of the following subsection.

<!-- #region -->
<div class="alert alert-info">
Expand Down Expand Up @@ -537,7 +537,7 @@ Given the array
... [ 0.84, 0.76, 0.25, 0.07]])
```

Replace the diagonal elements of `x` with `(-1, -2, -3, -4)`, and add `1` to all values in `x` that are greater than `0.8`.
Replace the diagonal elements of `x` with `(0, 1, 2, 3)`, and add `1` to all values in `x` that are greater than `0.8`.
</div>
<!-- #endregion -->

Expand All @@ -563,15 +563,15 @@ array([[ 3, 7, 11]])
```
<!-- #endregion -->

The rules for resolving the various possible combinations of basic and advanced indexing are nontrivial. Refer to the [official NumPy documentation](https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#combining-advanced-and-basic-indexing) for a detailed description for these rules. In practice, basic and advanced indexing can typically be used independently from one another.
The rules for resolving the various possible combinations of basic and advanced indexing are nontrivial. Refer to the [official NumPy documentation](https://numpy.org/doc/stable/reference/arrays.indexing.html#combining-advanced-and-basic-indexing) for a detailed description for these rules. In practice, basic and advanced indexing can typically be used independently from one another.


## Links to Official Documentation

- [Advanced Indexing](https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#advanced-indexing)
- [Logical Functions](https://docs.scipy.org/doc/numpy/reference/routines.logic.html)
- [numpy.where](https://docs.scipy.org/doc/numpy/reference/generated/numpy.where.html)
- [Combining Basics and Advanced Indexing](https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#combining-advanced-and-basic-indexing)
- [Advanced Indexing](https://numpy.org/doc/stable/reference/arrays.indexing.html#advanced-indexing)
- [Logical Functions](https://numpy.org/doc/stable/reference/routines.logic.html)
- [numpy.where](https://numpy.org/doc/stable/reference/generated/numpy.where.html)
- [Combining Basics and Advanced Indexing](https://numpy.org/doc/stable/reference/arrays.indexing.html#combining-advanced-and-basic-indexing)


## Reading Comprehension Solutions
Expand Down
12 changes: 6 additions & 6 deletions Python/Module3_IntroducingNumpy/ArrayTraversal.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ NumPy provides valuable tools for iterating over any array, such that each eleme
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f')]
```

Similarly, NumPy provides the [ndenumerate](https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndenumerate.html#numpy.ndenumerate) function, which enumerates each element in an N-dimensional array, specifying the N-dimensional index for each element.
Similarly, NumPy provides the [ndenumerate](https://numpy.org/doc/stable/reference/generated/numpy.ndenumerate.html#numpy.ndenumerate) function, which enumerates each element in an N-dimensional array, specifying the N-dimensional index for each element.
```python
>>> import numpy as np

Expand Down Expand Up @@ -77,7 +77,7 @@ See that each triplet of integers specifies the index for the corresponding arra
9
```

See [the official NumPy documentation](https://docs.scipy.org/doc/numpy/reference/routines.indexing.html#iterating-over-arrays) for a complete listing of functions that facilitate iterating over arrays. The official documentation also provides [a detailed treatment of array iteration](https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html#iterating-over-arrays), which is far more detailed than is warranted here. Next, we must discuss the default ordering that NumPy uses when traversing a N-dimensional array.
See [the official NumPy documentation](https://numpy.org/doc/stable/reference/routines.indexing.html#iterating-over-arrays) for a complete listing of functions that facilitate iterating over arrays. The official documentation also provides [a detailed treatment of array iteration](https://numpy.org/doc/stable/reference/arrays.nditer.html#iterating-over-arrays), which is far more detailed than is warranted here. Next, we must discuss the default ordering that NumPy uses when traversing a N-dimensional array.


<!-- #endregion -->
Expand Down Expand Up @@ -203,7 +203,7 @@ According to this discussion, `reshape` can effectively "undo" itself: `np.arang

## Links to Official Documentation

- [Definition of row major ordering](https://docs.scipy.org/doc/numpy/glossary.html#term-row-major)
- [Definition of column major ordering](https://docs.scipy.org/doc/numpy/glossary.html#term-column-major)
- [Routines for iterating over arrays](https://docs.scipy.org/doc/numpy/reference/routines.indexing.html#iterating-over-arrays)
- [Detailed description of array iteration](https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html#iterating-over-arrays)
- [Definition of row major ordering](https://numpy.org/doc/stable/glossary.html#term-row-major)
- [Definition of column major ordering](https://numpy.org/doc/stable/glossary.html#term-column-major)
- [Routines for iterating over arrays](https://numpy.org/doc/stable/reference/routines.indexing.html#iterating-over-arrays)
- [Detailed description of array iteration](https://numpy.org/doc/stable/reference/arrays.nditer.html#iterating-over-arrays)
2 changes: 1 addition & 1 deletion Python/Module3_IntroducingNumpy/BasicArrayAttributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,4 @@ The size, in bytes (8 bits is 1 byte), of each element of the array. For example

## Links to Official Documentation

- [Array attributes](https://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html#array-attributes)
- [Array attributes](https://numpy.org/doc/stable/reference/arrays.ndarray.html#array-attributes)
14 changes: 9 additions & 5 deletions Python/Module3_IntroducingNumpy/BasicIndexing.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ Basic indexing is triggered whenever a tuple of: integer, `slice`, `numpy.newaxi

**Reading Comprehension: Ellipsis**

Given a $N$-dimensional array, `x`, index into `x` such that you axis entry-0 of axis-0, the last entry of axis-$N-1$, slicing along all intermediate dimensions. $N$ is at least $2$.
Given a $N$-dimensional array, `x`, index into `x` such that you access entry-0 of axis-0, the last entry of axis-$N-1$, slicing along all intermediate dimensions. $N$ is at least $2$.

</div>

Expand Down Expand Up @@ -546,7 +546,6 @@ Which of the following expressions updates the data originally referenced by `x`
```python
# 5.
>>> np.log(x[1:3], out=x[1:3])
>>> y += 3
```

```python
Expand All @@ -556,7 +555,7 @@ Which of the following expressions updates the data originally referenced by `x`

```python
# 7.
>>> y = y + 2
>>> x = np.square(x)
```

```python
Expand All @@ -570,6 +569,11 @@ Which of the following expressions updates the data originally referenced by `x`
>>> f(y)
```

```python
# 10.
>>> np.square(y, out=y)
```

</div>
<!-- #endregion -->

Expand All @@ -584,8 +588,8 @@ Assignments to views of an array, augmented assignments, and NumPy functions tha

## Links to Official Documentation

- [Basic indexing](https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#indexing)
- [Definition of 'view'](https://docs.scipy.org/doc/numpy/glossary.html#term-view)
- [Basic indexing](https://numpy.org/doc/stable/reference/arrays.indexing.html#indexing)
- [Definition of 'view'](https://numpy.org/doc/stable/glossary.html#term-view)


## Reading Comprehension Solutions
Expand Down
36 changes: 19 additions & 17 deletions Python/Module3_IntroducingNumpy/Broadcasting.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ result-shape: 2 x 1


<!-- #region -->
NumPy provides the function [broadcast_to](https://docs.scipy.org/doc/numpy/reference/generated/numpy.broadcast_to.html#numpy.broadcast_to), which can be used to broadcast an array to a specified shape. This can help us build our intuition for broadcasting. Let's broadcast a shape-(3,4) array to a shape-(2,3,4) array:
NumPy provides the function [broadcast_to](https://numpy.org/doc/stable/reference/generated/numpy.broadcast_to.html#numpy.broadcast_to), which can be used to broadcast an array to a specified shape. This can help us build our intuition for broadcasting. Let's broadcast a shape-(3,4) array to a shape-(2,3,4) array:

```python
# Demonstrating `np.broadcast_to`
Expand Down Expand Up @@ -426,7 +426,7 @@ Normalize `x` such that *each of its rows, within each sheet, will sum to a valu

A digital image is simply an array of numbers, which instructs a grid of pixels on a monitor to shine light of specific colors, according to the numerical values in that array.

An RGB-image can thus be stored as a 3D NumPy array of shape-$(V, H, 3)$. $V$ is the number of pixels along the vertical direction, $H$ is the number of pixels along the horizontal, and the size-3 dimension stores the red, blue, and green color values for a given pixel. Thus a $(32, 32, 3)$ array would be a 32x32 RBG image.
An RGB-image can thus be stored as a 3D NumPy array of shape-$(V, H, 3)$. $V$ is the number of pixels along the vertical direction, $H$ is the number of pixels along the horizontal, and the size-3 dimension stores the red, blue, and green color values for a given pixel. Thus a $(32, 32, 3)$ array would be a 32x32 RGB image.

You often work with a collection of images. Suppose we want to store N images in a single array; thus we now consider a 4D shape-(N, V, H, 3) array. For the sake of convenience, let's simply generate a 4D-array of random numbers as a placeholder for real image data. We will generate 500, 48x48 RGB images:

Expand Down Expand Up @@ -663,19 +663,33 @@ The specific form of an equation can have a major impact on the memory-footprint

**Reading Comprehension: Checking the equivalence of the three pairwise distance functions**

Use the function [numpy.allclose](https://docs.scipy.org/doc/numpy/reference/generated/numpy.allclose.html) to verify that the three methods for computing the pairwise distances produce the same numerical results.
Use the function [numpy.allclose](https://numpy.org/doc/stable/reference/generated/numpy.allclose.html) to verify that the three methods for computing the pairwise distances produce the same numerical results.

</div>


## Links to Official Documentation

- [Basics of broadcasting](https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html#broadcasting)
- [Broadcasting routines](https://docs.scipy.org/doc/numpy/reference/routines.array-manipulation.html#changing-number-of-dimensions)
- [Basics of broadcasting](https://numpy.org/doc/stable/user/basics.broadcasting.html#broadcasting)
- [Broadcasting routines](https://numpy.org/doc/stable/reference/routines.array-manipulation.html#changing-number-of-dimensions)


## Reading Comprehension Solutions

<!-- #region -->
**Broadcast Compatibility: Solution**

1\. Incompatible

2\. `3 x 4`

3\. `8 x 3 x 1`

4\. `9 x 2 x 5`

5\. Incompatible
<!-- #endregion -->

<!-- #region -->
**Basic Broadcasting: Solution**

Expand All @@ -696,18 +710,6 @@ Generating the random array of 10,000, 2D points, and their "center-of-mass".
```
<!-- #endregion -->

**Broadcast Compatibility: Solution**

1\. Incompatible

2\. `3 x 4`

3\. `8 x 3 x 1`

4\. `9 x 2 x 5`

5\. Incompatible

<!-- #region -->
**Basic Broadcasting II: Solution**

Expand Down
Loading