Typorithm · easy

loc, iloc and shape-preserving selection

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

Step 1 of 4 · intro card

loc, iloc and shape-preserving selection

0%

Concept and contract

Use labels for named data and positions for explicit ordered slices.

loc selects labels, while iloc selects integer positions. A numeric label is still a label: a row labelled ten is not automatically the eleventh row. Column selection has the same distinction. A list of columns preserves a two-dimensional table, whereas selecting a single column name usually produces a Series. State the intended result shape before writing a selector so downstream code receives a stable interface.

The example first filters rows by a named score rule and projects named output columns, then takes the first two surviving rows by position. Filtering order and limiting order are distinct business decisions.

Mechanism and worked example

Build a typed two-column frame, form a boolean mask from score and use loc with both that mask and an explicit list of column names.

Build a typed two-column frame, form a boolean mask from score and use loc with both that mask and an explicit list of column names. Reset the retained row index for the presentation table. The final iloc slice chooses the first two qualifying rows without relying on whatever original labels survived filtering. Missing scores do not satisfy the threshold, because fillna(False) makes that policy explicit.

For scores nine, two, eight and seven at a threshold of seven, eligibility is decided before the limit. The first two qualifying roles are the first and third original rows. Limiting first would lose a valid candidate.

Complete worked example

python

import pandas as pd

def inspect_example(rows, threshold):
    frame = pd.DataFrame(rows, columns=["id", "score"]).astype({"id": "string", "score": "Float64"})
    eligible = frame["score"].ge(threshold).fillna(False)
    selected = frame.loc[eligible, ["id", "score"]].reset_index(drop=True)
    return selected.iloc[:2].reset_index(drop=True)
Reasoning
Build a typed two-column frame, form a boolean mask from score and use loc with both that mask and an explicit list of column names. Reset the retained row index for the presentation table. The final iloc slice chooses the first two qualifying rows without relying on whatever original labels survived filtering. Missing scores do not satisfy the threshold, because fillna(False) makes that policy explicit. For scores nine, two, eight and seven at a threshold of seven, eligibility is decided before the limit. The first two qualifying roles are the first and third original rows. Limiting first would lose a valid candidate.
Open in local Python playground ↗

Focused decision: context is in the complete example

python

eligible = frame["score"].ge(threshold).fillna(False)
selected = frame.loc[eligible, ["id", "score"]]
result = selected.iloc[:2]
Focused decision
Type this short table decision after reading its complete context. The complete imports, table 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 mistake takes two rows before applying eligibility.

The controlled mistake takes two rows before applying eligibility. That is easy to miss when early rows all qualify. Another error is using loc[:2] as though it were a half-open positional slice: label slices include their stop label when it is present. The result can contain an extra row, or use entirely different labels after a prior operation.

Avoid chained selection followed by assignment. This lesson only reads a selection; the later Copy-on-Write lesson shows a single loc assignment to update the owning frame. A read expression that looks convenient should not be generalized into an update recipe.

Controlled mistake: inspect the failing table contract

python

import pandas as pd

def inspect_example(rows, threshold):
    frame = pd.DataFrame(rows, columns=["id", "score"]).astype({"id": "string", "score": "Float64"})
    frame = frame.iloc[:2]
    eligible = frame["score"].ge(threshold).fillna(False)
    selected = frame.loc[eligible, ["id", "score"]].reset_index(drop=True)
    return selected.iloc[:2].reset_index(drop=True)
Reasoning
The controlled mistake takes two rows before applying eligibility. That is easy to miss when early rows all qualify. Another error is using loc[:2] as though it were a half-open positional slice: label slices include their stop label when it is present. The result can contain an extra row, or use entirely different labels after a prior operation. Avoid chained selection followed by assignment. This lesson only reads a selection; the later Copy-on-Write lesson shows a single loc assignment to update the owning frame. A read expression that looks convenient should not be generalized into an update recipe.
Open in local Python playground ↗

Independent practice

Change the presentation limit from the first two qualifying rows to the first one.

Change the presentation limit from the first two qualifying rows to the first one. Retain eligibility before limiting, the same named output columns and the reset index. The change is a single iloc slice boundary; no sorting, row deletion from the original input or new eligibility rule is required.

Predict a batch where the first row fails and the next two rows pass. Both the original and changed contracts must inspect beyond the initial failed row. Also predict an all-ineligible batch: the output is a typed empty table, rather than a placeholder result. These cases keep a small edit tied to a meaningful selection guarantee.

Step 1: Return only the first qualifying row, preserving filter-before-limit order. Step 2: Retain the working imports, input validation and table schemas. 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 pandas as pd

def inspect_example(rows, threshold):
    frame = pd.DataFrame(rows, columns=["id", "score"]).astype({"id": "string", "score": "Float64"})
    eligible = frame["score"].ge(threshold).fillna(False)
    selected = frame.loc[eligible, ["id", "score"]].reset_index(drop=True)
    return selected.iloc[:2].reset_index(drop=True)

# Independent task: Return only the first qualifying row, preserving filter-before-limit order.
Reasoning
Return only the first qualifying row, preserving filter-before-limit order.
Open in local Python playground ↗
  • Hint 1: Find the one field or branch that owns this policy.
  • Hint 2: Compare the first changed acceptance case with the retained baseline.

Solution, tests and trade-offs

The solution changes the final positional stop from two to one.

The solution changes the final positional stop from two to one. Assertions inspect exact IDs and values in their retained order, including missing-score and empty-result cases. The worked and practice cases deliberately put a rejected row near the beginning, so the premature-limit counterexample cannot pass merely by producing the right row count.

Notice that a correct count is weaker than a correct selection. Two rows can have the expected shape and still represent the wrong roles. Keep the eligibility predicate, identity column and ordered expected records in the same acceptance test. This principle will recur when grouping and reshaping larger tables.

Practice solution and acceptance checks

python

import pandas as pd

def inspect_example(rows, threshold):
    frame = pd.DataFrame(rows, columns=["id", "score"]).astype({"id": "string", "score": "Float64"})
    eligible = frame["score"].ge(threshold).fillna(False)
    selected = frame.loc[eligible, ["id", "score"]].reset_index(drop=True)
    return selected.iloc[:1].reset_index(drop=True)
Reasoning
The solution changes the final positional stop from two to one. Assertions inspect exact IDs and values in their retained order, including missing-score and empty-result cases. The worked and practice cases deliberately put a rejected row near the beginning, so the premature-limit counterexample cannot pass merely by producing the right row count. Notice that a correct count is weaker than a correct selection. Two rows can have the expected shape and still represent the wrong roles. Keep the eligibility predicate, identity column and ordered expected records in the same acceptance test. This principle will recur when grouping and reshaping larger tables.
Open in local Python playground ↗

Interview reasoning and next step

Explain when loc and iloc express different intentions, including the endpoint behavior of label slices.

Explain when loc and iloc express different intentions, including the endpoint behavior of label slices. Describe how selecting one column differs from selecting a list containing that column. Then walk through filtering before limiting with a concrete rejected first row. If output order matters, say where that order came from instead of assuming that eligibility automatically ranks results.

On the PC, type the two-stage selection and recall the final positional slice. In the app, reason about which rows survive. Next, examine why a nullable comparison can produce unknown values and why each filter needs an explicit missing-value policy.

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/pandas-lab-20261106.zip. Install pinned dependencies in an isolated Python environment. Run verify.py, then change the working exercise baseline and run --practice pd-select. The real pandas tables, exact schemas, unchanged inputs, CSV parser options and owned in-memory SQL reconciliation 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.

Use labels for named data and positions for explicit ordered slices.