Module 07 · Core

Sorting and index decisions

Order records deliberately and control which labels identify rows.

Before you start: Know filtering, loc, iloc, and table shape.

Python loads from this site on your first run.

Each run starts with fresh data. Download any exported files before another run. Your written answers and code drafts are saved on this device; export your work to keep a backup.

M07C01 · Explore · predict · practice

Sort rows by a value

sort_values() orders whole rows by one or more column values. ascending=False puts larger values first. It returns a new table, so assign the result if you want to keep the order. The index labels travel with their rows and are not automatically renumbered.

Read the example

df = students()
result = df.sort_values("Score", ascending=False).head(3)
print(result[["Student_ID", "Name", "Score"]])
print("Index labels:", result.index.tolist())
Verified example output · pandas 2.2.3
  Student_ID    Name  Score
5       S006  Fatima     95
2       S003   Chloe     91
9       S010   Jamal     89
Index labels: [5, 2, 9]

Watch for this. head(3) before sorting chooses the first three source rows, not the three highest scores.

Your turn

Find the three lowest scores instead. Keep Student_ID, Name, and Score in result.

For the code check, keep these result variable names: result. Different valid approaches are welcome.

Show a hint

Sort ascending and then take head(3).

Show one worked solution
df = students()
result = df.sort_values("Score", ascending=True).head(3)[["Student_ID", "Name", "Score"]]
print(result)

The three lowest scores are Hassan 58, Dana 65, and Khalid 68. Sorting whole rows keeps each score matched with its student.

Compare your explanations
  1. Read. Descending order, from larger scores to smaller scores.
  2. Predict. Fatima with 95, Chloe with 91, and Jamal with 89.
  3. Explain. The original row labels stay attached to the records when the rows are sorted.

One quick check

Does sort_values rearrange only the selected column's values?

What you should be able to explain. I can sort a table and identify the top or bottom records.

M07C02 · Explore · predict · practice

Specify a tie rule

Rows can tie on a sort column. With one column, kind="stable" preserves their existing order within a tie. To define a new tie rule, sort by several columns and give one ascending flag per column. Clear tie rules make results easier to reproduce and explain.

Read the example

df = pd.DataFrame({
    "Name": ["Chloe", "Amira", "Bilal", "Dana"],
    "Score": [80, 80, 95, 80]
})
result = df.sort_values("Score", ascending=False, kind="stable")
print(result)
Verified example output · pandas 2.2.3
    Name  Score
2  Bilal     95
0  Chloe     80
1  Amira     80
3   Dana     80

Watch for this. Alphabetical tie order must be requested explicitly; a stable sort preserves source order instead.

Your turn

Sort by Score descending, then Name ascending to break ties alphabetically.

For the code check, keep these result variable names: result. Different valid approaches are welcome.

Show a hint

Pass ["Score", "Name"] and ascending=[False, True].

Show one worked solution
df = pd.DataFrame({
    "Name": ["Chloe", "Amira", "Bilal", "Dana"],
    "Score": [80, 80, 95, 80]
})
result = df.sort_values(["Score", "Name"], ascending=[False, True])
print(result)

Bilal remains first with 95. The three scores of 80 are then ordered Amira, Chloe, Dana.

Compare your explanations
  1. Read. Chloe, Amira, and Dana all have 80.
  2. Predict. Chloe, Amira, then Dana, preserving their order in the original table.
  3. Explain. It provides a clear order among equal values, such as alphabetical order among students with the same score.

One quick check

What does a stable sort preserve for equal sort values?

What you should be able to explain. I can make the order of tied records explicit.

M07C03 · Explore · predict · practice

Set, check, and reset an index

An index labels rows; it is not automatically a unique ID. set_index() chooses the labels, and index.is_unique tells you whether any label repeats. reset_index() moves the current index back into a column and supplies new default row labels. Use reset_index(drop=True) only when you deliberately want to discard the current labels.

Read the example

df = students()
indexed = df.set_index("Student_ID")
print("Unique index:", indexed.index.is_unique)
result = indexed.reset_index()
print(result[["Student_ID", "Name"]].head(3))
Verified example output · pandas 2.2.3
Unique index: True
  Student_ID   Name
0       S001  Amira
1       S002  Bilal
2       S003  Chloe

Watch for this. Having an index does not guarantee that its labels are unique or non-missing.

Your turn

Set Student_ID as the index, select S003 and S001 in that order, and reset the selected index without losing the IDs.

For the code check, keep these result variable names: result. Different valid approaches are welcome.

Show a hint

Use .loc[["S003", "S001"]] followed by .reset_index().

Show one worked solution
df = students()
indexed = df.set_index("Student_ID")
selected = indexed.loc[["S003", "S001"]]
result = selected.reset_index()
print(result[["Student_ID", "Name"]])

The selected rows are Chloe and Amira. Their IDs remain in the Student_ID column, and their new row labels are 0 and 1.

Compare your explanations
  1. Read. It is True when no index label repeats. Separate checks are still needed for missing or invalid IDs.
  2. Predict. Yes. It is restored as a column, while the row index becomes 0 through 11.
  3. Explain. Student_ID is currently the index, so drop=True would discard those IDs instead of restoring them to a column.

One quick check

Which operation keeps the old index as a column?

What you should be able to explain. I can change an index without accidentally discarding record IDs.

M07C04 · Explore · predict · practice

Reindex to a requested order

reindex() aligns a table to a specified set of labels and their requested order. Existing labels bring their rows with them; new labels create missing values. This differs from sorting because you supply the desired labels explicitly. Use isna() to inspect newly missing cells.

Read the example

df = students().set_index("Student_ID")
result = df.reindex(["S003", "S001", "S999"])[["Name", "Score"]]
print(result)
print("Missing name:")
print(result["Name"].isna())
Verified example output · pandas 2.2.3
             Name  Score
Student_ID              
S003        Chloe   91.0
S001        Amira   88.0
S999          NaN    NaN
Missing name:
Student_ID
S003    False
S001    False
S999     True
Name: Name, dtype: bool

Watch for this. Reindexing can fail when source labels are duplicated; check uniqueness before using labels as identifiers.

Your turn

Reindex to S002, S001, and S004, in that order. Confirm that none of their names is missing.

For the code check, keep these result variable names: result. Different valid approaches are welcome.

Show a hint

Use only existing IDs and count missing names with .isna().sum().

Show one worked solution
df = students().set_index("Student_ID")
result = df.reindex(["S002", "S001", "S004"])[["Name", "Score"]]
print(result)
print("Missing names:", result["Name"].isna().sum())

The output is Bilal, Amira, Dana in the requested order, with no missing names. All requested labels exist.

Compare your explanations
  1. Read. It was requested in reindex but was absent from the source index, so pandas created a row of missing values.
  2. Predict. S003, S001, S999, matching the order passed to reindex.
  3. Explain. There is no source record for S999. Missing data does not establish a measured score or a fail decision.

One quick check

What can reindex do when a requested label does not exist?

What you should be able to explain. I can distinguish sorting existing rows from aligning to a requested index.

Further detail: official documentation for this topic.