Data Analysis with Python (pandas, polars, DuckDB) Module 2
pandas foundations interview questions
Interview questions on pandas foundations: short warm-ups, then what each harder question tests, the first step of a good answer and its follow-ups.
Warm-up questions
Short questions with short answers, each answered in full.
-
Fresher
What is the difference between a pandas Series and a DataFrame, and what is the index for?
-
Fresher
What is the difference between NaN and pd.NA in pandas?
Answered in the lesson Data types in pandas 3: str, nullable and Arrow
-
Fresher
What is the difference between loc and iloc?
Answered in the lesson Selecting rows and columns with loc and iloc
-
Fresher
How do the rank methods min, dense and first differ?
-
Fresher
What does Copy-on-Write change in pandas 3?
Answered in the lesson New columns, assign and Copy-on-Write
Questions with model answers
What each question tests, the first step of a good answer and the follow-ups to expect.
-
Fresher to mid
This month's revenue per customer (3,200 customers, from billing) is added to last month's (3,300, from the CRM). Both Series are indexed by customer ID. The result has 3,900 rows and 1,300 of them are NaN. What did pandas do, and how do you get a correct month-on-month comparison?
- What it tests
- Index alignment on labels, how unmatched or differently formatted keys create NaN, and choosing between a fill value and an inner match for the question being asked.
- First step
- With unique IDs and known matched revenues, the union count implies 2,600 matched IDs: 3,200 + 3,300 − 3,900. Check those assumptions before interpreting the 1,300 missing totals. Inspect both index dtypes, uniqueness, index.difference in each direction and missing revenue values; the row count alone cannot establish all of them.
- Follow-ups
-
- How do you tell new customers from IDs that only failed to match?
- When is fill_value=0 the wrong choice?
- How would you make this check part of the pipeline?
From the lesson Series, DataFrames and the index
Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.Opening the model answers with your pass…
Model answers open with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so the model answers can’t be opened at the moment. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Fresher to mid
A helper returns an order's amount with df.set_index("order_id").loc[order_id]["amount"]. It ran for months; today a caller fails with "The truth value of a Series is ambiguous". Explain what changed in the data, and rewrite the helper so it behaves predictably.
- What it tests
- Non-unique indexes, why the type that loc returns depends on the data, and lookups that return exactly one value or fail with a clear message.
- First step
- loc returns a Series for a label that occurs once and a DataFrame for a label that repeats, so ["amount"] became a Series of several amounts and the caller's comparison cannot decide. Count the repeats with df["order_id"].duplicated().sum() and find where they came from before changing any code.
- Follow-ups
-
- What should the helper do when an order ID repeats?
- Where do repeated IDs usually come from?
- Is set_index(verify_integrity=True) the right guard in pandas 3?
From the lesson Series, DataFrames and the index
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
After an upgrade to pandas 3, a cleaning step that strips spaces from every column where df[col].dtype == object has done nothing for a week, and nobody noticed. What changed, how do you find similar breakages in the codebase, and how do you write the check so it works on pandas 2 and 3?
- What it tests
- The pandas 3 str dtype, how a dtype check can fail without an error, finding the same pattern elsewhere and writing type checks and tests that hold across versions.
- First step
- pandas 3 infers the str dtype for text instead of object, so the condition is False for every text column and the loop skips them without raising anything. Replace it with pd.api.types.is_string_dtype, then search the code for other comparisons with object or "O".
- Follow-ups
-
- Which other pandas 3 changes break code without an error?
- Why would a column still be object after the upgrade?
- How do you make sure this cannot happen again?
From the lesson Data types in pandas 3: str, nullable and Arrow
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A daily file of 10 million orders (an ID with gaps, a city from a short list, quantity, price and a yes or no flag) must load inside a 1 GB container. On a server without PyArrow it takes about 1.3 GB in memory. Which dtypes do you choose, and how much memory do you expect?
- What it tests
- Estimating memory from per-value costs, choosing a dtype per column, keeping the peak of reading in mind and checking an estimate before it reaches production.
- First step
- Measure before choosing: read 100,000 rows, call memory_usage(deep=True) and scale by 100. The numbers cost 8 bytes a value each; text stored as Python objects costs about 50 to 55 bytes per short string, so the city and the flag hold most of the 1.3 GB.
- Follow-ups
-
- PyArrow cannot be installed on that server. What then?
- The file grows to 50 million rows. What changes?
- How do you check the estimate before production?
From the lesson Data types in pandas 3: str, nullable and Arrow
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Fresher to mid
Finance wants paid or refunded orders above 1,000. A teammate writes df[(df.status == "paid") | (df.status == "refunded") & (df.amount > 1000)] and gets 8,709 rows from 10,000 orders; finance expected about 6,000. Explain the result and write a filter that cannot be misread.
- What it tests
- The precedence of & over | in pandas masks, reading a filter through the counts of its parts, and writing conditions with isin and named masks.
- First step
- In Python & binds tighter than |, so the filter means "paid, or refunded and above 1,000": every paid order passes, whatever its amount. Count each part on its own, paid, refunded and above 1,000, and the 8,709 rows split into the pieces that let them in.
- Follow-ups
-
- Why is isin safer here than two comparisons joined with |?
- How do you test a filter like this one?
- What changes if amount has missing values?
From the lesson Selecting rows and columns with loc and iloc
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
After sorting by score, a function returns df.loc[0] as the top scorer and df.loc[:9] as the top ten. On the test file it looked right; in production the top scorer is wrong, and the top ten is 3 rows one day and 4,000 the next. Explain both bugs and fix the function.
- What it tests
- Label-based against position-based selection after a sort, how a label slice follows the current row order, and choosing iloc, head or nlargest for a top-N.
- First step
- sort_values keeps every row's label, so loc[0] is the row that came first in the file, wherever it is now. loc[:9] runs from the first row to wherever label 9 landed, so its length depends on the data. "The top ten" is a question about positions, not labels.
- Follow-ups
-
- Why did the test file hide both bugs?
- Which is better here, iloc, head or nlargest?
- How should ties at tenth place be handled?
From the lesson Selecting rows and columns with loc and iloc
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A product search runs df[df["name"].str.contains(term, case=False)] on whatever the user types. Searching for "C++" raises an error on the server, and searching for "1.5" also returns "105 mm lens". Explain both results, and make the filter safe for any text a user can type.
- What it tests
- str.contains reading its pattern as a regular expression, regex=False and escaping, missing values in the mask, and the risk of passing user input to a pattern.
- First step
- str.contains uses regular expressions unless regex=False. The dot in "1.5" can match the zero in "105". Arrow-backed text rejects "C++", while the Python engine accepts its possessive quantifier and may overmatch. For a literal substring, use regex=False and specify na=False when missing names must not match.
- Follow-ups
-
- Does the "C++" search fail the same way on every installation?
- When do you want a regular expression after all, and how do you make it safe?
- What does the filter do with products that have no name?
From the lesson Filtering, sorting and ranking
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A dashboard ranks colleges by pass rate, highest first, and the same data is sorted in pandas, polars and DuckDB in different parts of the pipeline. One tool shows a college with no result at the top, the others at the bottom. Explain each tool's behaviour and make all three agree.
- What it tests
- Default null ordering in pandas, polars and SQL engines, the difference between a null and a NaN value, and making order explicit across a pipeline.
- First step
- Write down each tool's default: pandas puts missing values last in both directions, polars puts nulls first in both, DuckDB puts NULLs last in both. Then check how the missing result is stored in each step: as a null, or as a floating-point NaN, which polars and DuckDB sort as a number.
- Follow-ups
-
- Why can a NaN behave differently from a null in polars and DuckDB?
- Where in the pipeline should the ordering rule live?
- Should a college with no result appear in the ranking at all?
From the lesson Filtering, sorting and ranking
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Fresher to mid
After an upgrade to pandas 3, a nightly job still finishes without errors, but the discount column it sets is now always 0, and its log is full of ChainedAssignmentError warnings that nobody reads. Explain what changed, how you find every affected line, and how you stop it from happening again.
- What it tests
- Copy-on-Write semantics, recognising chained assignment and inplace patterns, using warning filters to find them, and keeping such code out of a codebase.
- First step
- pandas 3 makes every indexing result behave as a copy, so a two-step assignment such as df[mask]["discount"] = 0.1 writes into a temporary object and df never changes. Each warning names its file and line: turn the warning into an error and run the job's tests to list them all.
- Follow-ups
-
- Which bug of this kind gives no warning at all?
- Is adding .copy() everywhere a fix?
- How do you keep these patterns out of new code?
From the lesson New columns, assign and Copy-on-Write
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A 6 GB DataFrame is processed on a 16 GB machine. The script runs df2 = df.reset_index(drop=True), then fills the missing values of df2 column by column, and memory climbs to 12 GB. Using pandas 3's Copy-on-Write, explain where the second 6 GB comes from, and change the script so it stays near 6 GB.
- What it tests
- How lazy copies turn into real copies, which references keep data alive, and writing memory-friendly pandas 3 code.
- First step
- reset_index returns a lazy copy that shares df's data. The first write to each column of df2 has to copy that column, because df still holds the original, so writing every column copies the whole table. Ask whether df is still needed after the reset_index call.
- Follow-ups
-
- Why did pandas 2 use the same 12 GB at a different moment?
- How do you measure whether a step copies data?
- When is an eager .copy() the right choice?
From the lesson New columns, assign and Copy-on-Write
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
All Data Analysis with Python (pandas, polars, DuckDB) interview questions · The Data Analysis with Python (pandas, polars, DuckDB) track