From ff0a522ab20cbcc0be9408eb96ee4f893278fa25 Mon Sep 17 00:00:00 2001 From: Aaron Meurer Date: Tue, 21 May 2024 19:25:39 -0600 Subject: [PATCH 1/8] Small fixes to the indexing guide --- .../multidimensional-indices/newaxis.md | 16 ++++++++-------- .../multidimensional-indices/tuples.md | 2 +- .../multidimensional-indices/what-is-an-array.md | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/indexing-guide/multidimensional-indices/newaxis.md b/docs/indexing-guide/multidimensional-indices/newaxis.md index 36800304..126d6ddd 100644 --- a/docs/indexing-guide/multidimensional-indices/newaxis.md +++ b/docs/indexing-guide/multidimensional-indices/newaxis.md @@ -15,11 +15,11 @@ None True ``` -`newaxis`, as the name suggests, adds a new axis. This new axis has size `1`. -The new axis is added at the corresponding location within the array. A size -`1` axis neither adds nor removes any elements from the array. Using the -[nested lists analogy](what-is-an-array.md), it essentially adds a new "layer" -to the list of lists. +`newaxis`, as the name suggests, adds a new axis to an array. This new axis +has size `1`. The new axis is added at the corresponding location within the +array shape. A size `1` axis neither adds nor removes any elements from the +array. Using the [nested lists analogy](what-is-an-array.md), it essentially +adds a new "layer" to the list of lists. ```py @@ -197,9 +197,9 @@ repeated. For example, suppose we have the two arrays ``` and suppose we want to compute an "outer" sum of `x` and `y`, that is, we want -to compute every combination of `i + j` where `i` is from `x` and `j` is from +to compute every combination of `a + b` where `a` is from `x` and `b` is from `y`. The key realization here is that what we want is simply to -repeat each entry of `x` 3 times, to correspond to each entry of `y`, and +repeat each entry of `x` 2 times, to correspond to each entry of `y`, and respectively repeat each entry of `y` 3 times, to correspond to each entry of `x`. And this is exactly the sort of thing broadcasting does! We only need to make the shapes of `x` and `y` match in such a way that the broadcasting will @@ -217,7 +217,7 @@ from `x`, and the second dimension will correspond to values from `y`, i.e., `a[i, j]` will be `x[i] + y[j]`. Thus the resulting array will have shape `(3, 2)`. So to make `x` (which is shape `(3,)`) and `y` (which is shape `(2,)`) broadcast to this, we need to make them `(3, 1)` and `(1, 2)`, respectively. -This can easily be done with `np.newaxis`. +This can easily be done with `np.newaxis`: ```py >>> x[:, np.newaxis].shape diff --git a/docs/indexing-guide/multidimensional-indices/tuples.md b/docs/indexing-guide/multidimensional-indices/tuples.md index 800ec402..cd99b321 100644 --- a/docs/indexing-guide/multidimensional-indices/tuples.md +++ b/docs/indexing-guide/multidimensional-indices/tuples.md @@ -42,7 +42,7 @@ array([[[16, 17, 18, 19], ``` We also observe that integer indices remove the axis, and slices keep the axis -(even when the resulting axis has size-1): +(even when the resulting axis has size 1): ```py >>> a[0].shape diff --git a/docs/indexing-guide/multidimensional-indices/what-is-an-array.md b/docs/indexing-guide/multidimensional-indices/what-is-an-array.md index f0454198..c4412f8b 100644 --- a/docs/indexing-guide/multidimensional-indices/what-is-an-array.md +++ b/docs/indexing-guide/multidimensional-indices/what-is-an-array.md @@ -26,9 +26,9 @@ subsets of it. ``` You can imagine all sorts of different things you'd want to do with your -scores that might involve selecting individual scores or ranges of scores (for +scores that might involve selecting individual scores or ranges of scores. For example, with the above examples, we could easily compute the average score of -our last three games, and see how it compares to our first game). So hopefully +our last three games, and see how it compares to our first game. So hopefully you are convinced that at least the types of indices we have learned so far are useful. From 6316e0a43437280ac2ce4161f0d1a6bf05486185 Mon Sep 17 00:00:00 2001 From: Aaron Meurer Date: Tue, 21 May 2024 19:59:10 -0600 Subject: [PATCH 2/8] Fix some wording --- docs/indexing-guide/multidimensional-indices/newaxis.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/indexing-guide/multidimensional-indices/newaxis.md b/docs/indexing-guide/multidimensional-indices/newaxis.md index 126d6ddd..f82e0c5a 100644 --- a/docs/indexing-guide/multidimensional-indices/newaxis.md +++ b/docs/indexing-guide/multidimensional-indices/newaxis.md @@ -245,7 +245,7 @@ array([[101, 201], [103, 203]]) ``` -Note: broadcasting automatically prepends shape `1` dimensions, so the +Note: broadcasting automatically prepends size-1 dimensions, so the `y[np.newaxis, :]` operation is unnecessary. ```py From 11a40f8e6f44404de294e415a889141f7e996481 Mon Sep 17 00:00:00 2001 From: Aaron Meurer Date: Tue, 21 May 2024 19:59:26 -0600 Subject: [PATCH 3/8] Make the beginning of the integer indices section clearer --- .../integer-arrays.md | 110 +++++++++++------- 1 file changed, 68 insertions(+), 42 deletions(-) diff --git a/docs/indexing-guide/multidimensional-indices/integer-arrays.md b/docs/indexing-guide/multidimensional-indices/integer-arrays.md index 4fc3c338..85dccdd5 100644 --- a/docs/indexing-guide/multidimensional-indices/integer-arrays.md +++ b/docs/indexing-guide/multidimensional-indices/integer-arrays.md @@ -78,25 +78,19 @@ Note that `a[idx]` above is not the same size as `a` at all. `a` has 4 elements and is 1-dimensional, whereas `a[idx]` has 6 elements and is 2-dimensional. `a[idx]` also contains some duplicate elements from `a`, and there are some elements which aren't selected at all. Indeed, we could take -*any* integer array of any shape, and as long as the elements are between 0 -and 3, `a[idx]` would create a new array with the same shape as `idx` with -corresponding elements selected from `a`. +*any* integer array `idx` of any shape, and as long as the elements are +between 0 and 3, `a[idx]` would create a new array with the same shape as +`idx` with corresponding elements selected from `a`. -A useful way to think about integer array indexing is that it generalizes -[integer indexing](../integer-indices.md). With integer indexing, we are -effectively indexing using a 0-dimensional integer array, that is, a single -integer.[^integer-scalar-footnote] This always selects the corresponding -element from the given axis and removes the dimension. That is, it replaces -that dimension in the shape with `()`, the "shape" of the integer index. - -Similarly, +The shape `a` is `(4,)` and the shape of `a[idx]` is `(2, 3)`, the same as the +shape of `idx`. In general, > **an integer array index `a[idx]` selects elements from the specified axis -> and replaces the dimension in the shape with the shape of the index array -> `idx`.** +> and replaces the selected dimension in the shape of `a` with the shape of +> the index array `idx`.** - -For example: +For example, in `a[idx].shape`, `4` is replaced with `(2, 3)`. Consider what +happens when `a` has more than one dimension: ``` >>> a = np.empty((3, 4)) @@ -107,13 +101,67 @@ For example: (3, 2, 2) ``` -In particular, even when the index array `idx` has more than one dimension, an +Here `a.shape` is `(3, 4)` and `idx.shape` is `(2, 2)`. In `a[idx].shape`, the +`3` is replaced with `(2, 2)`, giving `(2, 2, 4)`, and in `a[:, idx].shape`, +the `4` is replaced with `(2, 2)`, giving `(3, 2, 2)`. + +A useful way to think about integer array indexing is that it generalizes +[integer indexing](../integer-indices.md). With integer indexing, we are +effectively indexing using a 0-dimensional integer array, that is, a single +integer. This always selects the corresponding element from the given axis and +removes the dimension. That is, it replaces that dimension in the shape with +`()` (i.e., nothing), the "shape" of the integer index. The result of indexing +with an `int` and a corresponding 0-D array is exactly the +same.[^integer-scalar-footnote] + +[^integer-scalar-footnote]: + + (integer-scalar-footnote-ref)= + + There is one difference between `a[0]` and `a[asarray(0)]`. The + latter is considered an advanced index, so it does not create a + [view](views-vs-copies): + + ```py + >>> a = np.empty((2, 3)) + >>> a[0].base is a + True + >>> print(a[np.array(0)].base) + None + ``` + + In ndindex, + [`IntegerArray.reduce()`](ndindex.IntegerArray.reduce) will always convert + a 0-D array index into an [`Integer`](ndindex.integer.Integer). + +```py +>>> idx = np.asarray(0) # 0-D array +>>> idx.shape +() +>>> a = np.arange(12).reshape((3, 4)) +>>> a[idx].shape # replaces (3,) with () +(4,) +>>> a[:, idx].shape # repalces (4,) with () +(3,) +>>> a[idx] # a[asarray(0)] is the exact same as a[0] +array([0, 1, 2, 3]) +>>> a[0] +array([0, 1, 2, 3]) +``` + +Note that even when the index array `idx` has more than one dimension, an integer array index still only selects elements from a single axis of `a`. It would appear that this limits the ability to arbitrarily shuffle elements of -`a` using integer indexing. For instance, suppose we want to create the array -`[105, 100]` from the above 2-D `a`. Based on the above examples, it might not -seem possible, since the elements `105` and `100` are not in the same row or -column of `a`. +`a` using integer indexing. For instance, suppose we have the 2-D array + +``` +>>> a = [[100, 101, 102], +... [103, 104, 105]] +``` + +and we wanted use indexing to create the array `[105, 100]`. Based on the +above examples, it might not seem possible, since the elements `105` and `100` +are not in the same row or column of `a`. However, this is doable by providing multiple integer array indices: @@ -360,28 +408,6 @@ The ndindex methods [`expand()`](ndindex.Tuple.expand) will broadcast array indices together into a canonical form. -[^integer-scalar-footnote]: - - (integer-scalar-footnote-ref)= - - In fact, if the integer array index itself has - shape `()`, then the behavior is identical to simply using an `int` with - the same value. So it's a true generalization. In ndindex, - [`IntegerArray.reduce()`](ndindex.IntegerArray.reduce) will always convert - a 0-D array index into an [`Integer`](ndindex.integer.Integer). - - However, there is one difference between `a[0]` and `a[asarray(0)]`. The - latter is considered an advanced index, so it does not create a - [view](views-vs-copies): - - ```py - >>> a = np.empty((2, 3)) - >>> a[0].base is a - True - >>> print(a[np.array(0)].base) - None - ``` - (outer-indexing)= #### Outer Indexing From e60b1c763857668a327fd2bffb45c7fda9131fbc Mon Sep 17 00:00:00 2001 From: Aaron Meurer Date: Wed, 22 May 2024 11:38:01 -0600 Subject: [PATCH 4/8] Apply suggestions from code review --- .../indexing-guide/multidimensional-indices/integer-arrays.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/indexing-guide/multidimensional-indices/integer-arrays.md b/docs/indexing-guide/multidimensional-indices/integer-arrays.md index 85dccdd5..1e1acc05 100644 --- a/docs/indexing-guide/multidimensional-indices/integer-arrays.md +++ b/docs/indexing-guide/multidimensional-indices/integer-arrays.md @@ -82,7 +82,7 @@ there are some elements which aren't selected at all. Indeed, we could take between 0 and 3, `a[idx]` would create a new array with the same shape as `idx` with corresponding elements selected from `a`. -The shape `a` is `(4,)` and the shape of `a[idx]` is `(2, 3)`, the same as the +The shape of `a` is `(4,)` and the shape of `a[idx]` is `(2, 3)`, the same as the shape of `idx`. In general, > **an integer array index `a[idx]` selects elements from the specified axis @@ -141,7 +141,7 @@ same.[^integer-scalar-footnote] >>> a = np.arange(12).reshape((3, 4)) >>> a[idx].shape # replaces (3,) with () (4,) ->>> a[:, idx].shape # repalces (4,) with () +>>> a[:, idx].shape # replaces (4,) with () (3,) >>> a[idx] # a[asarray(0)] is the exact same as a[0] array([0, 1, 2, 3]) From dd9fb7c8ec384c0e92eca9e8749e2875805c47b7 Mon Sep 17 00:00:00 2001 From: Aaron Meurer Date: Wed, 22 May 2024 11:42:29 -0600 Subject: [PATCH 5/8] Small grammar fixes --- .../multidimensional-indices/integer-arrays.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/indexing-guide/multidimensional-indices/integer-arrays.md b/docs/indexing-guide/multidimensional-indices/integer-arrays.md index 85dccdd5..971860ae 100644 --- a/docs/indexing-guide/multidimensional-indices/integer-arrays.md +++ b/docs/indexing-guide/multidimensional-indices/integer-arrays.md @@ -1,7 +1,7 @@ # Integer Array Indices ```{note} -In this section, and [the next](boolean-arrays), do not confuse the *array +In this section and [the next](boolean-arrays), do not confuse the *array being indexed* with the *array that is the index*. The former can be anything and have any dtype. It is only the latter that is restricted to being integer or boolean. @@ -35,7 +35,7 @@ elements of the array in order (or possibly [reversed order](negative-steps) for slices), whereas this array has elements completely shuffled from `a`, and some are even repeated. -However, we could "cheat" a bit here, and do something like +However, we could "cheat" a bit here and do something like ```py >>> new_array = np.array([[a[0], a[2], a[0]], @@ -47,7 +47,7 @@ array([[100, 102, 100], This is the array we want. We sort of constructed it using only indexing operations, but we didn't actually do `a[idx]` for some index `idx`. Instead, -we just listed the index of each individual element. +we just listed the indices of each individual element. An integer array index is essentially this "cheating" method, but as a single index. Instead of listing out `a[0]`, `a[2]`, and so on, we just create a @@ -83,7 +83,7 @@ between 0 and 3, `a[idx]` would create a new array with the same shape as `idx` with corresponding elements selected from `a`. The shape `a` is `(4,)` and the shape of `a[idx]` is `(2, 3)`, the same as the -shape of `idx`. In general, +shape of `idx`. In general: > **an integer array index `a[idx]` selects elements from the specified axis > and replaces the selected dimension in the shape of `a` with the shape of @@ -160,8 +160,8 @@ would appear that this limits the ability to arbitrarily shuffle elements of ``` and we wanted use indexing to create the array `[105, 100]`. Based on the -above examples, it might not seem possible, since the elements `105` and `100` -are not in the same row or column of `a`. +above examples, this might not seem possible, since the elements `105` and +`100` are not in the same row or column of `a`. However, this is doable by providing multiple integer array indices: From a5add8b9391239d931bbb31179e88eab5e7bb9de Mon Sep 17 00:00:00 2001 From: Aaron Meurer Date: Wed, 22 May 2024 11:58:13 -0600 Subject: [PATCH 6/8] Add a section on bounds checking to the integer array indices page --- docs/indexing-guide/integer-indices.md | 1 + .../integer-arrays.md | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/docs/indexing-guide/integer-indices.md b/docs/indexing-guide/integer-indices.md index a9d78f60..9f4a40cb 100644 --- a/docs/indexing-guide/integer-indices.md +++ b/docs/indexing-guide/integer-indices.md @@ -140,6 +140,7 @@ Therefore, negative indices are primarily a syntactic convenience that allows one to specify parts of a list that would otherwise need to be specified in terms of the size of the list. +(integer-indices-bounds-checking)= If an integer index is greater than or equal to the size of the list, or less than negative the size of the list (`i >= len(a)` or `i < -len(a)`), then it is out of bounds and will raise an `IndexError`. diff --git a/docs/indexing-guide/multidimensional-indices/integer-arrays.md b/docs/indexing-guide/multidimensional-indices/integer-arrays.md index 32800250..6dc24022 100644 --- a/docs/indexing-guide/multidimensional-indices/integer-arrays.md +++ b/docs/indexing-guide/multidimensional-indices/integer-arrays.md @@ -333,6 +333,28 @@ array([100, 101, 103]) array([100, 101, 103]) ``` +### Bounds Checking + +As with [integer indices](../integer-indices.md), integer array indexing uses +bounds checking, with the [same rule as integer +indices](integer-indices-bounds-checking). + +> **If any entry in an integer array index is greater than `size - 1` or less +> than `-size`, where `size` is the size of the dimension being indexed, an +> `IndexError` is raised.** + +```py +>>> a = np.array([100, 101, 102, 103]) # as above +>>> a[[2, 3, 4]] +Traceback (most recent call last): + File "", line 1, in +IndexError: index 4 is out of bounds for axis 0 with size 4 +>>> a[[-5, -4, -3]] +Traceback (most recent call last): + File "", line 1, in +IndexError: index -5 is out of bounds for axis 0 with size 4 +``` + (integer-array-broadcasting)= ### Broadcasting From e3db1b60b755ea56b9bd347e3896ef1e1dbcc9d2 Mon Sep 17 00:00:00 2001 From: Aaron Meurer Date: Wed, 22 May 2024 12:10:56 -0600 Subject: [PATCH 7/8] Don't use a hyphen in "size 1" --- .../multidimensional-indices/boolean-arrays.md | 2 +- .../multidimensional-indices/integer-arrays.md | 8 ++++---- .../multidimensional-indices/newaxis.md | 18 +++++++++--------- .../multidimensional-indices/tuples.md | 4 ++-- docs/indexing-guide/other-topics.md | 4 ++-- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/indexing-guide/multidimensional-indices/boolean-arrays.md b/docs/indexing-guide/multidimensional-indices/boolean-arrays.md index 16923c45..b8125141 100644 --- a/docs/indexing-guide/multidimensional-indices/boolean-arrays.md +++ b/docs/indexing-guide/multidimensional-indices/boolean-arrays.md @@ -671,7 +671,7 @@ Or if it had no actual `0`s:[^0-d-mask-footnote] with the shape `(0,)` to the shape `(0,)`, and so this is what gets assigned, i.e., "nothing" (of shape `(0,)`) gets assigned to "nothing" (of matching shape `(0,)`). This is one reason why [broadcasting - rules](broadcasting) apply even to dimensions of size 0. + rules](broadcasting) apply even to dimensions of size `0`. ```py >>> a = np.asarray([1, 1, 2]) diff --git a/docs/indexing-guide/multidimensional-indices/integer-arrays.md b/docs/indexing-guide/multidimensional-indices/integer-arrays.md index 6dc24022..e002a96f 100644 --- a/docs/indexing-guide/multidimensional-indices/integer-arrays.md +++ b/docs/indexing-guide/multidimensional-indices/integer-arrays.md @@ -522,8 +522,8 @@ axis, i.e., exactly the arrays we want. This is why NumPy automatically broadcasts integer array indices together. -> **Outer indexing arrays can be constructed by inserting size-1 dimensions -> into the desired "outer" integer array indices so that the non-size-1 +> **Outer indexing arrays can be constructed by inserting size `1` dimensions +> into the desired "outer" integer array indices so that the non-size `1` > dimension for each is in the indexing dimension.** For example, @@ -540,7 +540,7 @@ Here, we use [newaxis](newaxis.md) along with `:` to turn `idx0` and `idx1` into shape `(2, 1)` and `(1, 3)` arrays, respectively. These then automatically broadcast together to give the desired outer index. -This "insert size-1 dimensions" operation can also be performed automatically +This "insert size `1` dimensions" operation can also be performed automatically with the {external+numpy:func}`numpy.ix_` function.[^ix-footnote] [^ix-footnote]: `ix_()` is currently limited to only support 1-D input arrays @@ -647,7 +647,7 @@ For example, consider: ... [103, 104, 105]]]) ``` -This is the same `a` as in the above examples, except it has an extra size-1 +This is the same `a` as in the above examples, except it has an extra size `1` dimension: ```py diff --git a/docs/indexing-guide/multidimensional-indices/newaxis.md b/docs/indexing-guide/multidimensional-indices/newaxis.md index f82e0c5a..b2fb9afd 100644 --- a/docs/indexing-guide/multidimensional-indices/newaxis.md +++ b/docs/indexing-guide/multidimensional-indices/newaxis.md @@ -77,7 +77,7 @@ within the index `a[0, :2]`: In each case, the exact same elements are selected: `0` always targets the first axis, and `:2` always targets the second axis. The only difference is -where the size-1 axis is inserted: +where the size `1` axis is inserted: ```py >>> a[np.newaxis, 0, :2] @@ -127,11 +127,11 @@ its position in the tuple index after removing any `newaxis` indices. Equivalently, `newaxis` indices can be though of as adding new axes *after* the existing axes are indexed. -A size-1 axis can always be inserted anywhere in an array's shape without +A size `1` axis can always be inserted anywhere in an array's shape without changing the underlying elements. An array index can include multiple instances of `newaxis` (or `None`). Each -will add a size-1 axis in the corresponding location. +will add a size `1` axis in the corresponding location. **Exercise:** Can you determine the shape of this array, given that `a.shape` is `(3, 2, 4)`? @@ -151,7 +151,7 @@ a[np.newaxis, 0, newaxis, :2, newaxis, ..., newaxis] In summary, -> **`np.newaxis` (which is just an alias for `None`) inserts a new size-1 axis +> **`np.newaxis` (which is just an alias for `None`) inserts a new size `1` axis in the corresponding location in the tuple index. The remaining, non-`newaxis` indices in the tuple index are indexed as if the `newaxis` indices were not there.** @@ -184,12 +184,12 @@ array([[ 0], `(3, 1)` column vector. But the most common usage is due to [broadcasting](broadcasting). The key idea -of broadcasting is that size-1 dimensions are not directly useful, in the +of broadcasting is that size `1` dimensions are not directly useful, in the sense that they could be removed without actually changing anything about the underlying data in the array. So they are used as a signal that that dimension can be repeated in operations. `newaxis` is therefore useful for inserting -these size-1 dimensions in situations where you want to force your data to be -repeated. For example, suppose we have the two arrays +these size `1` dimensions in situations where you want to force your data to +be repeated. For example, suppose we have the two arrays ```py >>> x = np.array([1, 2, 3]) @@ -245,7 +245,7 @@ array([[101, 201], [103, 203]]) ``` -Note: broadcasting automatically prepends size-1 dimensions, so the +Note: broadcasting automatically prepends size `1` dimensions, so the `y[np.newaxis, :]` operation is unnecessary. ```py @@ -255,7 +255,7 @@ array([[101, 201], [103, 203]]) ``` -As we saw [before](single-axis-tuple), size-1 dimensions may seem redundant, +As we saw [before](single-axis-tuple), size `1` dimensions may seem redundant, but they are not a bad thing. Not only do they allow indexing an array uniformly, they are also very important in the way they interact with NumPy's broadcasting rules. diff --git a/docs/indexing-guide/multidimensional-indices/tuples.md b/docs/indexing-guide/multidimensional-indices/tuples.md index cd99b321..2d6f8656 100644 --- a/docs/indexing-guide/multidimensional-indices/tuples.md +++ b/docs/indexing-guide/multidimensional-indices/tuples.md @@ -344,14 +344,14 @@ because it means that you can index the array uniformly.[^size-1-dimension-footnote] And this doesn't apply just to indexing. Many NumPy functions reduce the number of dimensions of their output (for example, {external+numpy:func}`numpy.sum`), but they have a `keepdims` -argument to retain the dimension as a size-1 dimension instead. +argument to retain the dimension as a size `1` dimension instead. [^size-1-dimension-footnote]: In this example, if we knew that we were always going to select exactly one element (say, the second one) from the first dimension, we could equivalently use `a[1, np.newaxis]` (see [](../integer-indices.md) and [](newaxis.md)). The advantage of this is that we would get an error if the first dimension of `a` didn't actually - have `2` elements, whereas `a[1:2]` would just silently give a size-0 + have `2` elements, whereas `a[1:2]` would just silently give a size `0` array. There are two final facts about tuple indices that should be noted before we diff --git a/docs/indexing-guide/other-topics.md b/docs/indexing-guide/other-topics.md index 0b18fba9..d7b66ad8 100644 --- a/docs/indexing-guide/other-topics.md +++ b/docs/indexing-guide/other-topics.md @@ -85,9 +85,9 @@ Broadcasting always happens automatically in NumPy whenever two arrays with different shapes are combined using any function or operator, assuming those shapes are broadcast compatible. The rule for broadcast compatibility is that the shorter of the shapes are prepended with length 1 dimensions so that they -have the same number of dimensions. Then any dimensions that are size 1 in a +have the same number of dimensions. Then any dimensions that are size `1` in a shape are replaced with the corresponding size in the other shape. The other -non-1 sizes must be equal or broadcasting is not allowed. +non-`1` sizes must be equal or broadcasting is not allowed. In the above example, we broadcast `(3, 2)` with `(2,)` by first extending `(2,)` to `(1, 2)` then broadcasting the size `1` dimension to the From 94100f0319a6f4915c4fb0ea7a7b979d519af0b2 Mon Sep 17 00:00:00 2001 From: Aaron Meurer Date: Wed, 22 May 2024 12:11:12 -0600 Subject: [PATCH 8/8] Grammar fixes --- docs/indexing-guide/other-topics.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/indexing-guide/other-topics.md b/docs/indexing-guide/other-topics.md index d7b66ad8..640801f6 100644 --- a/docs/indexing-guide/other-topics.md +++ b/docs/indexing-guide/other-topics.md @@ -30,7 +30,7 @@ array([[102, 104], [106, 108]]) ``` -However, you may have noticed that `x` and `y` doesn't always have to be two +However, you may have noticed that `x` and `y` don't always have to be two arrays with the same shape. For example, you can add a single scalar element to an array, and it will add it to each element. @@ -43,8 +43,8 @@ array([[2, 3], In the above example, we can think of the scalar `1` as a shape `()` array, whereas `x` is a shape `(2, 2)` array. Thus, `x` and `1` do not have the same shape, but `x + 1` is allowed via repeating `1` across every element of `x`. -This means taking `1` and treating it as if it were the shape `(2, 2)` array -`[[1, 1], [1, 1]]`. +This means NumPy is taking `1` and treating it as if it were the shape `(2, +2)` array `[[1, 1], [1, 1]]`. Broadcasting is a generalization of this behavior. Specifically, instead of repeating just a single number into an array, we can repeat just some @@ -75,11 +75,10 @@ array([[0, 2], [0, 2]]) ``` -This is what the array `y` looks like before it is combined with `x`, except -the power of broadcasting is that the repeated entries are not literally -repeated in memory. Broadcasting is implemented efficiently so that the -"repeated" elements actually refer to the same objects in memory. See -[](views-vs-copies) and [](strides) below. +This is what the array `y` looks like before it is combined with `x`. Although +note that broadcasting is implemented efficiently, so that the "repeated" +elements actually refer to the same objects in memory. See [](views-vs-copies) +and [](strides) below. Broadcasting always happens automatically in NumPy whenever two arrays with different shapes are combined using any function or operator, assuming those @@ -98,16 +97,18 @@ shape repeats the first axis 2 times along the second axis, while the second shape inserts a new axis at the beginning that repeats 3 times. We can think of `(3, 2)` as a "stack" of 3 shape `(2,)` arrays. Just as the -scalar 1 got repeated to match the full shape of `a` above, the shape `(2,)` +scalar `1` got repeated to match the full shape of `a` above, the shape `(2,)` array `y` gets repeated into a `(3,)` "stack" so it matches the shape of `x`. Additionally, size `1` dimensions are a signal to NumPy that that dimension is allowed to be repeated, or broadcasted, when used with another array where -that dimension is not size `1`. +the other dimensions match. It can be useful to think of broadcasting as repeating "stacks" of smaller -arrays in this way. The size `1` dimension rule allows these "stacks" to be -along any dimensions of the array, not just the last ones. +arrays in this way. The automatic prepending rule lets you automatically treat +array "stacking" along the last dimension, which is the most common, but the +size `1` dimension rule allows these stacks to be along any dimensions of +the array, not just the last ones. When it comes to indexing, one of the most useful types of index for use with broadcasting is [newaxis](./multidimensional-indices/newaxis.md), which lets