Python Pandas Interview Questions: Seven Worked Exercises

CAREER Published Updated 4 mins read By Leon Wei
Python Pandas Interview Questions: Seven Worked Exercises cover image

Quick summary

Summarize this blog with AI

These seven interview questions test whether you can explain pandas results as well as produce them. Each supplies complete data, a solution, an expected result, and a scoring rule. Try the prompt first. The snippets were executed with Python 3.12.14, pandas 2.2.3 with Copy-on-Write enabled, and pandas 3.0.6. Run them in order.

A strong answer states the output grain and missing-value policy before choosing a method. Award two points per question: one for the correct result and one for the explanation. This is a practice rubric, not a claim about any employer's hiring threshold.

1. Is 20 a label or a row position?

Prompt: Return the amount for index label 20, and then the amount in the second physical row. Explain why the two answers differ.

import pandas as pd
if pd.__version__.split(".")[0] == "2":
    pd.options.mode.copy_on_write = True

frame = pd.DataFrame({"amount": [5, 9, 2]}, index=[20, 10, 30])
print(frame.loc[20, "amount"])
print(frame.iloc[1, 0])

Expected output:

5
9

loc selects labels; iloc selects positions. A label can be an integer without becoming a position. A missing label raises KeyError. Also ask whether the index is unique: a repeated label can return multiple rows, changing the result's shape.

2. Impute one numeric column without changing a category

Prompt: Fill the missing age with the observed mean, preserve the missing city, and retain evidence of which ages were missing.

data = pd.DataFrame({"age": pd.Series([20, None, 40], dtype="Float64"),
                     "city": pd.Series(["A", None, "B"], dtype="string")})
data["age_was_missing"] = data["age"].isna()
data["age"] = data["age"].fillna(data["age"].mean())
print(data["age"].tolist())
print(data["age_was_missing"].tolist())
print(data["city"].isna().tolist())

Expected output:

[20.0, 30.0, 40.0]
[False, True, False]
[False, True, False]

Only age participates in the mean. Filling an entire mixed-type frame with a numeric mean is not a universal cleaning strategy. If every age is missing, the mean is also missing; reject, retain unknowns, or use a separately justified fallback. For a predictive model, learn imputation values from training data only.

3. Distinguish rows, observed values, and an unknown sum

Prompt: Count all rows, count observed amounts, and sum each region. Keep an all-missing group's sum unknown instead of zero.

sales = pd.DataFrame({"region": ["A", "A", "B"],
                      "amount": pd.Series([5, None, None], dtype="Int64")})
group = sales.groupby("region", sort=True)
print(group.size().to_dict())
print(group["amount"].count().to_dict())
totals = group["amount"].sum(min_count=1)
print(int(totals.loc["A"]), bool(pd.isna(totals.loc["B"])))

Expected output:

{'A': 2, 'B': 1}
{'A': 1, 'B': 0}
5 True

size counts rows, count excludes missing amounts, and min_count=1 requires at least one observed amount. A group with known zero is different from a group with no known amount. Missing group keys are dropped by default; use dropna=False when an explicit unknown-key group belongs in the denominator.

4. Reject a join that would duplicate facts

Prompt: Attach each customer's region to orders while proving the right side has at most one row per customer.

orders = pd.DataFrame({"order_id": [1, 2, 3], "customer_id": [7, 7, 8]})
customers = pd.DataFrame({"customer_id": [7, 8], "region": ["East", "West"]})
joined = orders.merge(customers, on="customer_id", how="left",
                      validate="many_to_one", indicator=True)
print(joined["region"].tolist())
print(joined["_merge"].astype(str).tolist())
try:
    orders.merge(pd.concat([customers, customers.iloc[[0]]]),
                 on="customer_id", validate="many_to_one")
except pd.errors.MergeError:
    print("duplicate dimension key rejected")

Expected output:

['East', 'East', 'West']
['both', 'both', 'both']
duplicate dimension key rejected

Dropping duplicates after a multiplied join does not establish which dimension row was authoritative. validate checks cardinality; indicator exposes unmatched rows. Neither proves that the IDs represent the right business entity. Explain both checks for full credit.

5. Do missing merge keys match?

Prompt: Predict this pandas merge and explain how to enforce a policy that excludes missing identities.

left = pd.DataFrame({"key": pd.Series([1, None], dtype="Int64")})
right = pd.DataFrame({"key": pd.Series([None], dtype="Int64"), "tag": ["unknown"]})
print(len(left.merge(right, on="key", how="inner")))
print(len(left.dropna(subset=["key"]).merge(
    right.dropna(subset=["key"]), on="key", how="inner")))

Expected output:

1
0

pandas matches null join keys with one another, unlike ordinary SQL equality joins. Decide whether that match has business meaning. Excluding unresolved identities can be correct, but retain them in an exception report if reconciliation requires every input row.

6. Keep the missing month visible

Prompt: Sum January and March values into month-end bins, leaving February unknown when no observation exists.

series = pd.Series([10, 5, 8], index=pd.to_datetime(
    ["2026-01-01", "2026-01-31", "2026-03-01"]))
monthly = series.resample("ME").sum(min_count=1)
print(monthly.index.strftime("%Y-%m-%d").tolist())
print([None if pd.isna(x) else float(x) for x in monthly])

Expected output:

['2026-01-31', '2026-02-28', '2026-03-31']
[15.0, None, 8.0]

ME is the month-end alias used by both tested versions. Zero would assert known zero activity; no observation need not justify that assertion. This fixture uses timezone-naive calendar dates. Convert real timestamps to the reporting timezone before deciding which month contains them.

7. Update the intended frame explicitly

Prompt: Change amounts below five to zero in a copy, leaving the original unchanged under Copy-on-Write.

original = pd.DataFrame({"amount": [2, 8]})
updated = original.copy()
updated.loc[updated["amount"] < 5, "amount"] = 0
print(original["amount"].tolist())
print(updated["amount"].tolist())

Expected output:

[2, 8]
[0, 8]

A single loc assignment targets updated directly. Chained assignment is not a reliable way to mutate the parent frame; pandas 3 uses Copy-on-Write semantics. Full credit requires explaining which object should change, rather than merely suppressing an assignment warning.

Evaluate the explanation, not just the method name

Review each answer for labels versus positions, row counts versus observed values, unknown versus zero, and the intended join grain. Before optimizing, establish those semantics and compare memory/runtime on representative data. For analyst-oriented business cases, continue with data analyst interview exercises; for experiment and leakage questions, use the data science set.

References: indexing, merge validation and null-key behavior, time series, and Copy-on-Write.

Interview Prep

Begin Your SQL, Python, and R Journey

Master 230 interview-style coding questions and build the data skills needed for analyst, scientist, and engineering roles.

Related Articles

All Articles