Typorithm · easy

Indexing, slices and preserving a row axis

pythonnumpynumerical-computingindependent-practice
Saved on this device
Full lesson · 4 learning steps Open any exercise for focused practice
1

Step 1 of 4 · intro card

Indexing, slices and preserving a row axis

0%

Concept and contract

Select rows and columns intentionally, including the difference between a scalar index and a one-column slice.

Indexing answers which coordinates to select and what shape the result should retain. For a two-dimensional table, data[:, 1] selects a one-dimensional column, while data[:, 1:2] keeps a two-dimensional one-column table. The numbers can be identical even though later broadcasting behaves differently. A scalar row index similarly removes an axis; a row slice preserves it.

This lesson accepts a non-empty matrix and extracts the first two rows of its first column as an independent two-dimensional result. Ordinary slicing allows a stop beyond the available row count, so a one-row input is still valid. The contract deliberately distinguishes permissive slice stops from out-of-range scalar indexing.

Mechanism and worked example

The worked expression uses a row slice and a column slice together, then copies the selection before returning it.

The worked expression uses a row slice and a column slice together, then copies the selection before returning it. For a three-by-two input, the result has shape (2, 1). For a one-row input, it has shape (1, 1). This is an explicit interface choice, not a universal rule that every selected column should stay two-dimensional.

Trace each colon separately: the first pair addresses rows and the second addresses columns. Negative indexes count from the end, but this function does not need them. Treat ellipsis and inserted axes as later tools, not as shortcuts that obscure the coordinate system in a first exercise.

Complete worked example

python

import numpy as np

def inspect_example(rows):
    data = np.array(rows, dtype=np.float64, copy=True)
    if data.ndim != 2 or 0 in data.shape:
        raise ValueError("expected a non-empty matrix")
    return data[:2, :1].copy()
Reasoning
The worked expression uses a row slice and a column slice together, then copies the selection before returning it. For a three-by-two input, the result has shape (2, 1). For a one-row input, it has shape (1, 1). This is an explicit interface choice, not a universal rule that every selected column should stay two-dimensional. Trace each colon separately: the first pair addresses rows and the second addresses columns. Negative indexes count from the end, but this function does not need them. Treat ellipsis and inserted axes as later tools, not as shortcuts that obscure the coordinate system in a first exercise.
Open in local Python playground ↗

Focused decision: context is in the complete example

python

selected = data[:2, :1].copy()
assert selected.ndim == 2
Focused decision
Type this short numerical decision after reading its complete context. The complete imports, array construction, validation, and result checks remain in the worked example. Typing records practice; only the downloadable computer lab executes Python.

Counterexamples and common mistakes

The controlled counterexample uses an integer column index.

The controlled counterexample uses an integer column index. It returns the expected first-column numbers but collapses the column dimension, which can later turn a column-wise operation into row-wise broadcasting. A printout or a len check will not reveal every instance of this mistake. Another common error is swapping the row and column selectors because both examples happen to be square.

Basic slices generally share storage with their source, so writing through a slice can affect its parent. This function chooses a copy for an independent result. The dedicated ownership lesson will compare that choice with deliberate shared views and advanced indexing.

Controlled mistake: inspect the failing numerical contract

python

import numpy as np

def inspect_example(rows):
    data = np.array(rows, dtype=np.float64, copy=True)
    if data.ndim != 2 or 0 in data.shape:
        raise ValueError("expected a non-empty matrix")
    return data[:2, 0].copy()
Reasoning
The controlled counterexample uses an integer column index. It returns the expected first-column numbers but collapses the column dimension, which can later turn a column-wise operation into row-wise broadcasting. A printout or a len check will not reveal every instance of this mistake. Another common error is swapping the row and column selectors because both examples happen to be square. Basic slices generally share storage with their source, so writing through a slice can affect its parent. This function chooses a copy for an independent result. The dedicated ownership lesson will compare that choice with deliberate shared views and advanced indexing.
Open in local Python playground ↗

Independent practice

Keep the output two-dimensional and change the selected rows to the final two observations.

Keep the output two-dimensional and change the selected rows to the final two observations. Preserve first-column selection and independence. This is a small slice-boundary task: the function should still accept one row and return the rows in their existing order.

Write the expected coordinates for a four-row matrix, then verify the single-row case. Do not reverse the rows or sort the values. Row order carries observation order here, and a shortcut that returns the two largest values would answer a different question.

Step 1: Return the last two rows of the first column, keeping its column axis. Step 2: Retain the working imports, input validation and array shapes. Change the stated policy, run the supplied practice cases, then explain the newly accepted or rejected boundary.

Practice starter: solve before reading the solution

python

import numpy as np

def inspect_example(rows):
    data = np.array(rows, dtype=np.float64, copy=True)
    if data.ndim != 2 or 0 in data.shape:
        raise ValueError("expected a non-empty matrix")
    return data[:2, :1].copy()

# Independent task: Return the last two rows of the first column, keeping its column axis.
Reasoning
Return the last two rows of the first column, keeping its column axis.
Open in local Python playground ↗
  • Hint 1: A negative slice start counts from the final row.
  • Hint 2: Keep :1 on the column axis and change only the row slice.

Solution, tests and trade-offs

The changed row slice uses -2: and keeps the column range :1.

The changed row slice uses -2: and keeps the column range :1. Copying remains explicit. Cases with asymmetric matrices expose axis swaps, while a single-row case checks that the code relies on slice semantics rather than requiring exactly two available rows. The lab verifies shape and dtype separately from numeric equality.

An independent output may cost an allocation, but returning a view and documenting that shared ownership would be a different valid contract. Neither approach is automatically faster in a complete application: unnecessary copies cost bandwidth, while accidental mutation can invalidate later results and caches.

Practice solution and acceptance checks

python

import numpy as np

def inspect_example(rows):
    data = np.array(rows, dtype=np.float64, copy=True)
    if data.ndim != 2 or 0 in data.shape:
        raise ValueError("expected a non-empty matrix")
    return data[-2:, :1].copy()
Reasoning
The changed row slice uses -2: and keeps the column range :1. Copying remains explicit. Cases with asymmetric matrices expose axis swaps, while a single-row case checks that the code relies on slice semantics rather than requiring exactly two available rows. The lab verifies shape and dtype separately from numeric equality. An independent output may cost an allocation, but returning a view and documenting that shared ownership would be a different valid contract. Neither approach is automatically faster in a complete application: unnecessary copies cost bandwidth, while accidental mutation can invalidate later results and caches.
Open in local Python playground ↗

Interview reasoning and next step

In an interview, compare a[:, 0], a[:, :1], a[0] and a[:1] using exact shapes.

In an interview, compare a[:, 0], a[:, :1], a[0] and a[:1] using exact shapes. Explain which dimensions disappear, what a slice stop beyond the array does, and when a returned selection shares memory. These distinctions prevent many errors that otherwise look like mysterious broadcasting failures.

Practice by typing the compact two-axis selection and then recalling it from its stated shape. In the app, answer the shape questions and inspect the examples. Next, build a boolean condition that selects matching rows without using Python scalar boolean operators on an array.

Optional stretch — after the core task works: Add one independently reasoned boundary case and explain its expected value before running it.

Computer practice: https://applydjinn.com/typorithm/numpy-lab-20261106.zip. Install pinned dependencies in an isolated Python environment. Run verify.py, then change the working exercise baseline and run --practice np-indexing. The real NumPy arrays, numerical contracts, random state checks and temporary numeric files use owned fixtures only. No production database, feed, account or paid service is used. This lab executes Python; the PC typing trainer and native reading progress do not execute it.

Select rows and columns intentionally, including the difference between a scalar index and a one-column slice.