Choose the Readings Without Losing Their Place
Botie may need one morning, a run of mornings, or selected greenhouses. We need to express each request precisely and know whether editing the selection will change the original report.
10 sections · 4 questions · 2 coding challenges
The arrow keys move between sections too.
Working on Part of a Large Scientific Record
BOTIE
NumPy distinguishes basic slicing, which can share storage, from advanced indexing, which gathers values into a new array. Those documented rules explain both the convenience of selection and the need for care when editing it.
Sources for this history
Which Part of the Report Did We Ask For?
A report with hundreds of rows is useful only if we can retrieve the observations we need. Sometimes they are adjacent. Sometimes we need particular positions in a particular order. Those requests should not be confused.
We will follow a small temperature table through slices and explicit index selections, then check which results share storage with the original. This matters whenever we prepare data while keeping the original measurements available.
Keep the original order visible
Rows are mornings; columns are north, middle, south.
Monday
- 10
- 20
- 30
Tuesday
- 14
- 22
- 36
Wednesday
- 16
- 24
- 38
What we can now calculate
Gather chooses the days; transpose changes which meaning occupies a row. Neither step averages or sorts the selected temperatures.
Explore the full example
Choose an example, then change a value. Follow the calculation below to see which result changes and why. These are small teaching examples; the construction later asks you to choose the operations yourself.
BOTIE
Result from these values
| 16 | 10 |
| 24 | 20 |
| 38 | 30 |
Follow the operations
1. Days by greenhouse
10 20 30 14 22 36 16 24 38 2. Requested day indices
- 02
- 10
3. Gather selected entries
16 24 38 10 20 30 4. Swap rows and columns
16 10 24 20 38 30 5. Result
16 10 24 20 38 30
These workshop wires carry values rather than shared NumPy storage. Copy and view behaviour is demonstrated and checked in Python. Editing this example does not change the workshop tests.
1. Read a Slice From Start to Stop
A slice has a start, a stop, and an optional step. The stop is excluded. Leaving a boundary empty uses the corresponding end of the axis. A negative index counts back from the end, so minus one selects the last entry.
In a matrix we supply a selector for each axis, separated by a comma. Selecting with a single integer removes that axis; selecting a one-entry slice keeps it.
Keep a row, or keep a one-row table
These selections contain the same first-day readings, but the resulting shapes differ. The last expression selects every other greenhouse from the final day.
import numpy as np
a = np.array([[10,20,30],[14,22,36],[16,24,38]])
print(a[0].tolist())
print(a[0].shape)
print(a[0:1].shape)
print(a[-1, ::2].tolist())[10, 20, 30]
(3,)
(1, 3)
[16, 38]Keeping an axis can make a later calculation easier to align. The step of two selects columns zero and two; it does not multiply the temperatures.
2. Choose Positions in an Explicit Order
An integer index array requests positions rather than a continuous range. It can reorder entries or repeat them. For multiple axes, two index lists normally identify pairs of coordinates. If we want every combination of chosen rows and chosen columns, we need to express that different request.
Pairs of coordinates or a rectangular selection
The paired request retrieves row two, column one and row zero, column two. ix_ creates selectors for all combinations of those row and column choices.
import numpy as np
a = np.array([[10,20,30],[14,22,36],[16,24,38]])
print(a[[2, 0]].tolist())
print(a[[2, 0], [1, 2]].tolist())
print(a[np.ix_([2, 0], [1, 2])].tolist())[[16, 24, 38], [10, 20, 30]]
[24, 30]
[[24, 38], [20, 30]]The rectangle has two selected rows and two selected columns. Pairwise selection has only two entries. Neither operation is a mistake by itself; they answer different questions.
3. Decide Whether an Edit Should Reach the Original
A name is not a copy. Assigning a second name to an array gives both names the same object. A basic slice also shares the underlying numerical storage. An advanced selection gathers into independent storage. Use copy when independence is part of the task.
Inspect sharing before editing
shares_memory reports whether these arrays overlap in memory. A slice and an integer-index selection can show the same values while behaving differently when changed.
import numpy as np
a = np.array([10, 20, 30])
view = a[:2]
gathered = a[[0, 1]]
independent = a.copy()
print(np.shares_memory(a, view))
print(np.shares_memory(a, gathered))
view[0] = 11
gathered[1] = 99
print(a.tolist())
print(independent.tolist())True
False
[11, 20, 30]
[10, 20, 30]The slice changed the original first reading. The gathered array and explicit copy did not. np.asarray is useful for accepting an input as an array, but it may return an existing array unchanged; it is not a promise to make a copy.
4. Count Repeated Positions Deliberately
Repeated retrieval is straightforward, but repeated updates need care. When advanced indexing gathers a temporary array, an in-place-looking update can lose repeated contributions. If every occurrence should add to a count, NumPy's add.at performs an update at each supplied position.
Two alerts for the same greenhouse
Our saved alert IDs contain greenhouse one twice. We compare an indexed increment with accumulation that processes every occurrence.
import numpy as np
ids = np.array([1, 1, 2])
buffered = np.zeros(3, dtype=int)
buffered[ids] += 1
counts = np.zeros(3, dtype=int)
np.add.at(counts, ids, 1)
print(buffered.tolist())
print(counts.tolist())[0, 1, 1]
[0, 2, 1]The second result records all three alerts. This distinction will matter when later lessons accumulate repeated token IDs or category observations.
Check yourself
Questions on Parts 1 to 4
Question 1 of 4
How many axes survive the slice?
Use this setup. The code is given; its result is for you to work out.
import numpy as np
a = np.array([[10,20,30],[14,22,36]])
selected = a[0:1]Try it with Botie
Build with Botie
Write and run Python