fillna / dropna
Fill or drop missing values per column, and why fillna(0) leaves string columns alone.
On this page
Show code in
Every code block on the page follows this.
You will learn
- How to fill missing values with one value or one value per column
- Why fillna(0) leaves string columns alone
- How dropna's how, thresh and subset options decide which rows go
- When filling is wrong and null should stay null
df.fillna(value) replaces nulls only in columns whose type matches the value; pass a dict such as {"city": "unknown", "qty": 0} to fill per column. df.dropna() removes rows with any null; subset, how="all" and thresh make it precise. Both also exist as df.na.fill and df.na.drop.fillna
result = leads.fillna({"city": "unknown", "score": 0})
SELECT lead_id, name, coalesce(city, 'unknown') AS city, coalesce(score, 0) AS score, phone FROM leads
Switch to PySpark to edit and run this example in your browser.
Each column gets its own default, and columns not in the dict keep their nulls. SQL has no fillna: coalesce(col, default) per column is the equivalent.
The type rule
fillna(0) fills only numeric columns, and fillna("n/a") fills only string columns. Nothing errors when a column is skipped, so leads.fillna(0) leaves city null and it is easy to think everything was filled. A dict makes the intent explicit and avoids the surprise.
dropna
result = leads.dropna(thresh=3)
SELECT * FROM leads WHERE (CASE WHEN lead_id IS NOT NULL THEN 1 ELSE 0 END + CASE WHEN name IS NOT NULL THEN 1 ELSE 0 END + CASE WHEN city IS NOT NULL THEN 1 ELSE 0 END + CASE WHEN score IS NOT NULL THEN 1 ELSE 0 END + CASE WHEN phone IS NOT NULL THEN 1 ELSE 0 END) >= 3
Switch to PySpark to edit and run this example in your browser.
| Call | Keeps a row when | Leads kept |
|---|---|---|
dropna() | No column is null | 1 |
dropna(how="all") | At least one column is not null | all 5 (lead_id is never null) |
dropna(subset=["city"]) | city is not null | 1, 4 |
dropna(thresh=3) | At least 3 columns are not null | 1, 4, 5 |
thresh overrides how. subset limits which columns are checked, and it combines with both.
When not to fill
A null often carries meaning: "not measured", "not applicable", "not yet known". Filling a missing score with 0 makes avg(score) lower, because avg ignores nulls but not zeros. Fill for display and for columns where a default is truly correct (a missing quantity in a cart is 0); keep nulls in data used for statistics.
Input
| score values | avg |
|---|---|
| 80, null, null, null, 55 | 67.5 |
Output
| score values | avg |
|---|---|
| 80, 0, 0, 0, 55 | 27.0 |
avg(score) before and after fillna(0)
Related tools
coalesce(a, b, c)fills from other columns, not a constant: see the coalesce lesson.df.na.replace(["N/A", ""], None, subset=["city"])turns placeholder strings into real nulls first, so fillna and dropna see them.- For a forward fill (use the last known value), use
last(col, ignorenulls=True)over a window.
Common mistakes
Assuming fillna(0) filled every column
Filling before computing averages
dropna() with no subset on wide tables
Treating "" and "N/A" as missing
Key takeaways
- fillna with a dict fills per column; a single value only fills matching types.
- dropna: subset picks the columns, how="all" or thresh decides how many nulls are too many.
- Filling changes statistics; keep meaningful nulls.
- Turn placeholder strings into nulls before cleaning.
Check yourself
3 questions1. df has a null in a string column city. What does df.fillna(0) do to it?
Show the answer
Leaves it null. A numeric fill value only applies to numeric columns.
2. Which call keeps rows with at least 3 non-null values?
Show the answer
dropna(thresh=3). thresh is the minimum number of non-null values a row needs.
3. Scores are 80, null, 60. What is avg(score) after fillna(0)?
Show the answer
46.67. (80 + 0 + 60) / 3. Without filling, avg ignores the null and gives 70.
Practice it
Interview problems that use fillna / dropna: write the PySpark, run it, and get graded on hidden tests.
Keep going
Up next · lesson 13 of 35 · 3 min readdropDuplicates
Remove duplicate rows or keys, and why "keep the latest row" needs a window instead.
Related lessons
coalescePySpark functions · 4 min read
filter / wherePySpark functions · 3 min read
last(ignorenulls)
Previous: when / otherwise
Primary sources: DataFrame.fillna · DataFrame.dropna