Get AI summaries of any video or article — Sign up free
Python Pandas Tutorial (Part 3): Indexes - How to Set, Reset, and Use Indexes thumbnail

Python Pandas Tutorial (Part 3): Indexes - How to Set, Reset, and Use Indexes

Corey Schafer·
4 min read

Based on Corey Schafer's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.

TL;DR

Pandas indexes provide the labels that `.loc` uses for row selection, turning lookups into direct label-based queries.

Briefing

Pandas indexes turn row and column lookups from “search by position” into “search by label,” and that shift makes real survey data far easier to query. The tutorial starts with a small people table where the default index is just 0, 1, 2, then shows how swapping that index to a meaningful identifier—like email—lets lookups become direct and readable.

Using the sample DataFrame, the index is initially an unnamed, range-based integer identifier. Since pandas doesn’t strictly enforce uniqueness, indexes are usually chosen from values that are effectively unique in practice. Email is used as the example: after setting it with `df.set_index('email')`, the email values appear as the left-side index (displayed in bold and carrying the column name). A key detail is that `set_index` does not modify the existing DataFrame unless `inplace=True` is provided. Without `inplace`, printing `df` still shows the original default index; with `inplace=True`, the DataFrame’s index actually changes, and `df.index` confirms the index values and its name.

Once email becomes the index, label-based selection with `.loc` becomes the natural way to retrieve rows. Instead of using the old integer labels, the tutorial demonstrates selecting a specific person by passing the email string to `df.loc[...]`, and optionally narrowing to a column (e.g., retrieving `last_name`). Trying to use the old integer labels with `.loc` triggers an error because those labels no longer exist. For integer-based retrieval by position, the tutorial points to `.iloc` as the alternative.

The tutorial then moves from toy data to a Stack Overflow survey dataset. The survey includes a `respondent` column that functions as a unique ID per row, so the default range index is replaced with that ID. This can be done either after loading via `df.set_index('respondent', inplace=True)` or during import by passing `index_col='respondent'` to `read_csv`. With the respondent ID as the index, selecting the first respondent becomes as simple as `df.loc[1]`.

A second DataFrame, `schema`, maps survey column names to question text. Setting the schema’s index to the `column` field makes it possible to look up what a column means without manually scanning the entire schema. For instance, looking up `hobbiest` returns the question text (“Do you code as a hobby”), and looking up a less familiar label like `MGR idiot` retrieves the full prompt. To improve usability, the tutorial also sorts the schema index alphabetically using `schema_df.sort_index()`, with an option for descending order via `ascending=False`. If sorting should persist for later operations, `inplace=True` is used.

Overall, indexes are presented as a practical tool for making `.loc` lookups fast, readable, and aligned with how identifiers are already embedded in the data—especially when working with large, schema-driven datasets.

Cornell Notes

Indexes in pandas replace the default row numbering with meaningful labels, enabling direct lookups using `.loc`. The tutorial shows setting an index with `set_index('email')`, and highlights that changes don’t persist unless `inplace=True` is used. After switching the index to email, rows are retrieved by label (e.g., `df.loc['cory@example.com']`), while integer-based selection requires `.iloc`. In the Stack Overflow survey example, using `respondent` as `index_col` (or via `set_index`) makes respondent-based queries straightforward. The same idea applies to the `schema` DataFrame: setting its index to `column` allows quick retrieval of question text for labels like `hobbiest` and `MGR idiot`, and sorting the index makes navigation easier.

Why does choosing a custom index (like email) change how you query a DataFrame?

Because `.loc` uses index labels, not row positions. After `df.set_index('email', inplace=True)`, the left-side index becomes the email strings. That means `df.loc['cory@gmail.com']` returns the row for that person, and selecting a column (e.g., `last_name`) works alongside it. The old integer labels (0, 1, 2) no longer exist as labels, so using them with `.loc` raises an error. If you still want integer position access, `.iloc` remains available.

What’s the difference between `df.set_index(...)` and `df.set_index(..., inplace=True)`?

`df.set_index('email')` returns a new DataFrame with the index changed, but it doesn’t alter the original `df` unless you explicitly keep the returned object or set `inplace=True`. In the tutorial, printing `df` after calling `set_index` without `inplace` still shows the default range index. Adding `inplace=True` makes the index change persist in the existing DataFrame, and `df.index` then lists the email values and the index name.

How can you set the respondent ID as the index when loading Stack Overflow survey CSV files?

Either set it after loading with `df.set_index('respondent', inplace=True)` or set it during import by passing `index_col='respondent'` to `read_csv`. The tutorial uses `index_col='respondent'` so the DataFrame is “cleaned up” immediately: the respondent IDs become the index labels, making lookups like `df.loc[1]` return the first respondent’s row.

How does setting the `schema` DataFrame index help interpret survey columns?

The `schema` DataFrame maps each survey column name to its question text. By setting the schema index to the `column` field (e.g., `index_col='column'`-style logic via `set_index`), `.loc` can retrieve question metadata directly by label. Looking up `hobbiest` returns the question text (“Do you code as a hobby”), and looking up `MGR idiot` returns “How confident are you that your manager knows what they’re doing,” without scanning the entire schema manually.

Why sort the schema index, and how is it done?

Sorting makes it easier to find a specific label when browsing many schema entries. The tutorial uses `schema_df.sort_index()` to sort alphabetically. For reverse order, it passes `ascending=False`. If the sorted order should persist for later steps, `inplace=True` is used so the schema DataFrame stays sorted.

Review Questions

  1. When you switch a DataFrame’s index from the default integers to email strings, which indexer should you use for label-based lookup, and what happens if you try the old integers with it?
  2. What two methods does the tutorial present for setting `respondent` as the index when working with CSV data, and how do they differ in timing?
  3. How does setting the `schema` DataFrame index to the `column` field change the way you retrieve question text for labels like `hobbiest`?

Key Points

  1. 1

    Pandas indexes provide the labels that `.loc` uses for row selection, turning lookups into direct label-based queries.

  2. 2

    `set_index` does not modify the original DataFrame unless `inplace=True` is used (or the returned DataFrame is assigned).

  3. 3

    After setting a custom index (e.g., email), integer labels from the default index are no longer valid for `.loc` and will raise errors.

  4. 4

    Use `.iloc` when you want integer position access even after changing the index.

  5. 5

    When loading CSV survey data, `read_csv(..., index_col='respondent')` can set the index immediately for cleaner downstream queries.

  6. 6

    Setting the `schema` DataFrame index to the `column` field enables instant retrieval of question text for any survey column label via `.loc`.

  7. 7

    Sorting indexes with `sort_index()` (and optionally `ascending=False` / `inplace=True`) improves navigation through large label sets.

Highlights

Setting `email` as the index makes `.loc` lookups read like the data itself: `df.loc['cory@gmail.com']` returns the matching row.
Pandas keeps changes out of place by default—`set_index` requires `inplace=True` (or reassignment) to permanently update the DataFrame.
In the Stack Overflow survey, using `respondent` as `index_col` turns “first row” into “respondent 1,” making queries more meaningful.
Indexing the `schema` DataFrame by `column` turns column-name interpretation into a one-line `.loc` lookup for labels like `hobbiest` and `MGR idiot`.
Sorting the schema index with `sort_index()` makes it practical to find specific question labels without manual scanning.

Topics

  • Pandas Indexing
  • Setting Index
  • Using .loc and .iloc
  • read_csv index_col
  • Schema Lookups

Mentioned

  • CSV