Data science interview bank

Questions interviewers actually ask, each answered at the length you would say it aloud, with the topic to reread if you were not sure.

20 questions Junior Senior
All levels Junior Mid Senior
Reveal one by one Show all answers
Report an error

Python visualization

2 questions
01 How do Figure, Axes, Axis, and Artist differ in Matplotlib? Junior common reveal ▾ hide ▴

A Figure is the complete output container and owns the canvas, layout, and one or more Axes. An Axes is one plotting area; most commands such as plot, bar, set_title, and legend belong there. Each Axes normally has x and y Axis objects that manage scales, tick locations, formatters, and tick labels. Artist is the shared base concept for visible elements such as lines, rectangles, text, legends, and images. This hierarchy matters because explicit ownership tells you where an update, label, or save operation will take effect.

read more Matplotlib
Was this clear?
02 Why is Matplotlib’s object-oriented interface preferred in reusable code? Mid common reveal ▾ hide ▴

Pyplot maintains a current Figure and current Axes, which is convenient for a short interactive session but makes behavior depend on call order. Reusable code is clearer when it receives an Axes, adds artists through ax methods, and saves through the owning Figure. That design works unchanged when a plot moves into a multi-panel layout and lets tests inspect the exact objects created. Pyplot still has a role in constructing and closing figures. The important distinction is explicit ownership, not a ban on importing matplotlib.pyplot.

read more Matplotlib
Was this clear?

Visual encoding

1 question
03 How do you make color comparable across multiple Matplotlib panels? Mid occasional reveal ▾ hide ▴

Use one normalization object and one colormap for every comparable artist. The normalization maps domain values into the colormap range, so shared vmin, vmax, and any midpoint guarantee that one value receives one color across panels. Add a common colorbar with the measurement unit. Do not let each scatter or image infer limits independently, because identical colors can then mean different values. Choose limits from domain thresholds or a predefined comparison range, and decide explicitly whether out-of-range values are clipped, extended on the colorbar, or rejected.

read more Matplotlib
Was this clear?

Rendering and lifecycle

1 question
04 What makes Matplotlib batch rendering reliable in a headless service? Senior occasional reveal ▾ hide ▴

Choose a non-interactive backend such as Agg at process startup, before importing pyplot or creating figures. Give each request or job explicit ownership of its Figure, save through fig.savefig, and close that exact Figure in a finally block. Avoid mutating global rcParams from library functions; use rc_context for bounded style changes. Validate the generated file rather than assuming a successful call proves its dimensions or format. Tests should run without a display, force a save failure, and assert that pyplot has no leftover figure numbers afterward.

read more Matplotlib
Was this clear?

Python arrays

1 question
05 What information makes up the practical contract of a NumPy array? Junior common reveal ▾ hide ▴

Start with shape, dtype, and the meaning of every axis. Shape alone is not enough: a matrix shaped (32, 10) could mean samples by features or time by sensors. Ownership belongs in the contract too, because a basic slice may share its buffer while advanced indexing returns a copy. For numerical code, add policies for empty axes, NaN and infinity, integer range, and acceptable floating tolerance. A reliable function states its input and output shapes relative to named axes and documents whether it mutates, returns a view, or allocates an independent result.

read more NumPy
Was this clear?

Array semantics

1 question
06 How does NumPy broadcasting work, and how can a valid broadcast still be wrong? Mid common reveal ▾ hide ▴

NumPy compares shapes from the trailing axes. Two axis lengths are compatible when they are equal or one is 1, and missing leading axes behave as length 1. The result takes the larger length on each compatible axis. That mechanical rule knows nothing about domain meaning. Adding shapes (n, 1) and (n,) is legal but produces (n, n), which is often an accidental outer operation. I predict the result shape first, keep reduced axes when useful, test with non-square dimensions, and name each axis in the interface rather than trusting an expression merely because it runs.

read more NumPy
Was this clear?

Memory and ownership

1 question
07 When does NumPy return a view rather than a copy, and why does the distinction matter? Mid common reveal ▾ hide ▴

Basic slicing usually returns a view that shares the source buffer, while integer-array and Boolean indexing return copies. Reshape and ravel may return either, depending on layout; flatten always copies. The distinction matters because writing through a view can mutate data owned by the caller, while copying changes allocation and isolates later writes. I use np.shares_memory when overlap must be established and call copy explicitly at an ownership boundary. Function documentation and tests should say whether input may change and should modify both input and output to verify the promised relationship.

read more NumPy
Was this clear?

Generated code review

2 questions
08 What do you review before trusting a generated NumPy preprocessing pipeline? Senior occasional reveal ▾ hide ▴

I trace shape, dtype, axis meaning, and ownership after every operation. Then I look for broadcasts that are legal but semantically wrong, integer arrays used for in-place division, matrix multiplication written as element-wise multiplication, and basic slices modified as temporary copies. Boundary tests include empty input, one row, constant columns, NaN, infinity, extreme integer values, and non-contiguous views. Random work should receive a Generator instead of resetting global state. Finally, I run a tiny non-square example by hand and compare it with the code, because equal dimensions can hide an axis error surprisingly well.

read more NumPy
Was this clear?
20 What do you review before trusting AI-generated visualization code? Senior common reveal ▾ hide ▴

I trace a few records from input through filtering, aggregation, sorting, and encoding to their marks, labels, and legend entries. This catches the common bug where values are sorted without labels or a post-aggregation table is paired with an old index. I list every axis and color domain, unit, baseline, and transformation, checking that comparable panels share scales. Boundary tests cover empty input, duplicate keys, missing and infinite values, negatives, constant columns, and extremes. Finally, I inspect the delivered artifact at its real size for clipped text, inaccessible color-only cues, hidden gaps, and unexplained uncertainty.

Was this clear?

Tabular data contracts

1 question
09 What belongs in the contract of a DataFrame passed between pipeline stages? Mid common reveal ▾ hide ▴

I specify required columns, each column’s dtype and meaning, the row index semantics, and which keys must be unique. The contract also states whether missing values are allowed, how unknown categories are represented, and whether the function may mutate its input. For a transformation, I describe the output shape relative to the input and name invariants such as conserved revenue or preserved left-side orders. At runtime I validate these properties at boundaries, because a DataFrame can have the expected column names while still carrying reordered labels, duplicate keys, or silently promoted dtypes.

read more pandas
Was this clear?

Selection and ownership

1 question
10 How do .loc and Copy-on-Write affect assignment in pandas 3.0? Mid common reveal ▾ hide ▴

Copy-on-Write makes an object derived from another pandas object behave like a copy: changing the derived object does not update the source. That makes chained assignment such as df[mask][“status”] = value incapable of changing df, because the second operation writes to an intermediate object. I use df.loc[mask, “status”] = value to name the target rows and column in one operation. If the API should return an independent result, I copy explicitly and return it. Tests compare both source and result after assignment so the ownership promise is observable rather than inferred.

read more pandas
Was this clear?

Grouping and aggregation

1 question
11 When should you use agg, transform, or apply after groupby? Mid common reveal ▾ hide ▴

I choose by the required output shape. agg produces one or more summary values per group and usually reduces rows; named aggregation also fixes the output column names. transform returns a result aligned to the original index, so it fits group totals, shares, ranks, and centered values that must be assigned back to each row. apply is the escape hatch for operations whose result cannot be expressed by built-in aggregation or transformation. Before using it, I state the expected index and shape explicitly and check whether direct column operations express the rule more clearly.

read more pandas
Was this clear?

Joins and integrity

2 questions
12 How do you make a pandas merge safe against silent row multiplication? Senior common reveal ▾ hide ▴

I start by naming the intended cardinality: one-to-one, one-to-many, many-to-one, or genuinely many-to-many. Then I check key nulls and uniqueness on the constrained side and pass the matching validate value to merge. I often add indicator=True during validation to count left-only, right-only, and matched rows. After the merge I compare row counts and domain totals that should be preserved. I also handle null keys explicitly because pandas can match null keys across both inputs, unlike common SQL behavior. Normalizing case or whitespace belongs before these checks, not after the join.

read more pandas
Was this clear?
16 How do you review a Polars join for silent data multiplication or loss? Senior occasional reveal ▾ hide ▴

I first name the intended cardinality: one-to-one, one-to-many, many-to-one, or genuinely many-to-many. Then I validate nulls and uniqueness on constrained keys and pass the matching value such as validate=“m:1” to join. I choose the join type from the retention rule, not convenience, and inspect unmatched keys before filling right-side nulls. After execution I compare row counts and business totals that should be conserved. I also sort explicitly when output order is part of the contract, because a group or join result should not be treated as implicitly ordered.

read more Polars
Was this clear?

Polars execution

1 question
13 How do DataFrame and LazyFrame differ in Polars, and where should collect appear? Junior common reveal ▾ hide ▴

A DataFrame contains materialized columns, so eager operations run as they are called. A LazyFrame contains a logical query plan. Methods add scan, filter, projection, aggregation, and join nodes until collect executes the plan and returns a DataFrame. I use eager mode for small data already in memory and lazy scans for file pipelines that can benefit from whole-plan optimization. Reusable transformations should normally accept and return LazyFrame objects. I put collect or a sink at an application boundary where I can observe I/O, memory use, schema errors, and post-execution invariants.

read more Polars
Was this clear?

Expressions and schemas

1 question
14 What is a Polars expression context, and why can sibling expressions not depend on a new alias? Mid common reveal ▾ hide ▴

An expression describes a column computation, while its context determines shape behavior. select returns expression outputs, with_columns preserves existing columns, filter selects rows, and group_by().agg() reduces groups. Sibling expressions in one context are evaluated against the same input schema and may run independently. If one sibling creates revenue, another cannot read pl.col(“revenue”) during that same with_columns call. I either chain a second with_columns call, which makes revenue part of the next input schema, or bind the revenue formula to an expression variable and reuse the formula directly.

read more Polars
Was this clear?

Data contracts

1 question
15 How do schema, null, and NaN rules affect a reliable Polars pipeline? Mid common reveal ▾ hide ▴

I treat column names, dtypes, nullability, units, and key rules as the input contract. CSV has no native schema, so important fields need schema or schema_overrides instead of sample-dependent inference. Polars null is a missing value represented separately from the data, while NaN is a floating-point value. fill_null does not replace NaN, and fill_nan does not replace null. I count and test them independently, decide whether invalid casts should fail or become null, and validate ranges after parsing. A matching schema still cannot prove that quantities are nonnegative or identifiers are unique.

read more Polars
Was this clear?

Visualization design

1 question
17 How do you choose a chart type from an analytical question? Junior common reveal ▾ hide ▴

I first name the relationship the reader must judge: comparison, trend, distribution, association, or composition. Then I state the data grain, field types, units, missing-value policy, and delivery context. Categories compared on one number usually start with bars or dots; continuous time starts with a line that preserves gaps; one numeric distribution starts with a histogram or empirical distribution; two numeric fields start with a scatter plot. These are starting points, not rules. I keep the chart only if its visual channels make the intended comparison direct and do not conceal important records or transformations.

Was this clear?

Scales and integrity

1 question
18 When is a chart scale misleading even if every plotted value is correct? Mid common reveal ▾ hide ▴

A scale misleads when its geometry encourages a comparison the domain does not support. Truncating a bar baseline changes length ratios, while independent panel limits make equal heights or colors mean different values. A log axis can be valid for ratios but must reject or explicitly handle values outside its domain and show the transformation in ticks and labels. Axis breaks, clipped outliers, reversed directions, and dual y-axes all require explicit justification. I inspect the complete domain, units, baseline, transformation, and shared-scale requirements, then test a few known values against their rendered positions.

Was this clear?

Missingness and uncertainty

1 question
19 How should a visualization represent missing data and uncertainty without conflating them? Mid occasional reveal ▾ hide ▴

Missingness says an observation is absent or unavailable; uncertainty qualifies an observed value or estimate. I preserve missing states in the data and break a time-series line rather than dropping the row and connecting across it. If I interpolate, I label the method and interval and keep the original missing flag. For uncertainty, I name the quantity shown—standard deviation, standard error, prediction interval, or confidence interval—along with its level, method, and sampling unit. I also show sample size or raw distributions where possible, because a polished band cannot compensate for sparse or dependent observations.

Was this clear?