Pandas fillna: different values for different columns
Fill missing city and score values with separate defaults while leaving other columns and the input DataFrame unchanged.
Example check: Worked and guided code samples are checked against CPython 3.13. Practice uses Pyodide 0.29.5 (Python 3.13) in your browser. How we check lessons
Video lesson: Pandas fillna: different values for different columns
The preview is stored on this site. YouTube loads only when you press Play. Watch on YouTube
Jump to a chapter
Read the video transcript
Select a timestamp to watch that moment on YouTube.
- 00:00
Pandas fillna replaces values that pandas recognizes as missing, such as None, NaN, and pd.NA. A single scalar applies the same replacement across the selected DataFrame, which is rarely appropriate when columns represent different kinds of information. Filling a city label with 0 and a numeric score with 'Unknown' produces confusing data and can change a useful numeric dtype into an object dtype. Today we will test the claim with a tiny example, inspect a misleading first attempt, and finish with a verification case. Fill missing city and score values with separate defaults while leaving other
- 00:40
columns and the input DataFrame unchanged. Pass a dictionary to DataFrame.fillna for column-specific defaults: frame.fillna({'city': 'Unknown', 'score': 0}). Keys are column labels and values are replacements. Columns omitted from the mapping remain untouched. The call returns a new DataFrame by default, so the original is available for comparison and audit. The first run is intentionally incomplete or incorrect. The city column gets a numeric zero instead of a meaningful label. Read the actual output before editing the code; a familiar-looking command can still answer the wrong question.
- 01:21
Begin by naming what each column represents. In the sample, city is text, score is numeric, and note is optional free text. Replacing every missing cell with 0 makes the numeric column appear complete, but it also makes city equal a number. A table can still print without an error while its schema becomes less useful. Pandas recognizes None and NaN as missing here. An empty string is not treated as missing by fillna, so a blank city would require a separate normalization decision. Do not merge these two policies casually: an empty string might be intentionally different from unknown in some data sources.
- 02:02
We use a second run to make the cause visible. The printed values are small enough to check by hand. If they disagree with your prediction, pause and identify the assumption that changed. The direct answer to pandas fillna different values for different columns is a dictionary passed to DataFrame.fillna. Its keys are column names. The city key maps to 'Unknown'; the score key maps to 0. Each replacement applies only where that named column is missing. Existing values, including the Rome label and numeric four, remain as they were. The call returns a new DataFrame by default, so a caller can inspect both versions.
- 02:43
This is useful for data cleaning because the original record is evidence of what arrived. Avoid inplace=True unless there is a clear reason to discard that original state. For larger pipelines, make the fill mapping a named policy rather than scattered literals. Now compare the corrected run with the earlier one. The important change is the rule encoded in the operation, not merely the final display. Run the code and inspect the returned values as well as their interpretation. A missing value is different from an empty string or a string containing spaces. fillna does not rewrite blank text; normalize text separately if blank text is
- 03:23
invalid in your source. It also does not decide whether zero is an honest replacement for an unknown score. Zero may change averages or totals, so choose a default only when the data contract justifies it; otherwise keep missing values or use an imputation rule and document it. A mapping need not cover every column. Here note is intentionally absent from the fill mapping, so a missing note remains missing. That is often better than inventing a note that no one wrote. Verify with pd.isna instead of comparing a missing value with equality; NaN does not behave like an ordinary string or number in comparisons.
- 04:08
Also inspect the input after computing fixed. By default fillna did not mutate it, so its city is still missing. This makes it possible to compare raw and cleaned records or test the transformation. Filling unknown scores with zero may bias averages, so a production analysis must justify that rule; preserving missing scores can be the more honest choice when zero has a real measurement meaning. The final run checks a different condition so a special-case answer cannot pass unnoticed. Try the linked browser task and use the guide when you need a smaller step. The source links on the lesson page give the complete API behavior.
- 04:49
The browser task uses in-memory records with city, score, and note fields. In local Python install pandas with python -m pip install pandas. The task fills only city and score, leaves note missing, and verifies the source remains unchanged. It checks a second DataFrame so the answer cannot be a hard-coded output list. Before adopting a fill rule, count how many values are missing in each column with isna().sum(). A default can hide a source-quality problem if a large fraction of records is incomplete. Keep the original DataFrame or a copy so you can measure what changed. If a numeric column uses pandas nullable integer dtype, choose a replacement that
- 05:32
preserves its intended type and verify the dtype after filling. The examples use floating scores because missing values in a regular numeric column commonly produce floats. The important habit is to choose a meaning first, then apply the fill operation.
Understand the concept
Pandas fillna replaces values that pandas recognizes as missing, such as None, NaN, and pd.NA. A single scalar applies the same replacement across the selected DataFrame, which is rarely appropriate when columns represent different kinds of information. Filling a city label with 0 and a numeric score with 'Unknown' produces confusing data and can change a useful numeric dtype into an object dtype.
Pass a dictionary to DataFrame.fillna for column-specific defaults: frame.fillna({'city': 'Unknown', 'score': 0}). Keys are column labels and values are replacements. Columns omitted from the mapping remain untouched. The call returns a new DataFrame by default, so the original is available for comparison and audit.
A missing value is different from an empty string or a string containing spaces. fillna does not rewrite blank text; normalize text separately if blank text is invalid in your source. It also does not decide whether zero is an honest replacement for an unknown score. Zero may change averages or totals, so choose a default only when the data contract justifies it; otherwise keep missing values or use an imputation rule and document it.
The browser task uses in-memory records with city, score, and note fields. In local Python install pandas with python -m pip install pandas. The task fills only city and score, leaves note missing, and verifies the source remains unchanged. It checks a second DataFrame so the answer cannot be a hard-coded output list.
- fillna recognizes null markers, not empty strings
- a mapping selects different defaults by column
- omitted columns remain missing
- default fillna returns a new DataFrame
See it step by step
Read the code, predict the output, then compare it with the result.
01. See why one scalar is too broad
import pandas as pd
frame = pd.DataFrame({'city':[None], 'score':[None]})
print(frame.fillna(0).loc[0].tolist())[0, 0]A numeric zero in a city field does not mean unknown city.
02. Fill two columns differently
import pandas as pd
frame = pd.DataFrame({'city':[None,'Rome'], 'score':[4.0,None]})
fixed = frame.fillna({'city':'Unknown', 'score':0})
print(fixed['city'].tolist())
print(fixed['score'].tolist())['Unknown', 'Rome']
[4.0, 0.0]The mapping applies only the named default to each column.
03. Keep unrelated missing data and original input
import pandas as pd
frame = pd.DataFrame({'city':[None], 'score':[None], 'note':[None]})
fixed = frame.fillna({'city':'Unknown', 'score':0})
print(pd.isna(fixed.loc[0,'note']))
print(pd.isna(frame.loc[0,'city']))True
TrueThe note remains missing and the input is not changed.
A closer look
Follow the reasoning, inspect each result, then try the suggested changes in the console below.
Identify missing markers and field meanings
Begin by naming what each column represents. In the sample, city is text, score is numeric, and note is optional free text. Replacing every missing cell with 0 makes the numeric column appear complete, but it also makes city equal a number. A table can still print without an error while its schema becomes less useful.
Pandas recognizes None and NaN as missing here. An empty string is not treated as missing by fillna, so a blank city would require a separate normalization decision. Do not merge these two policies casually: an empty string might be intentionally different from unknown in some data sources.
import pandas as pd
frame = pd.DataFrame({'city':[None], 'score':[None]})
print(frame.fillna(0).loc[0].tolist())[0, 0]- Run the scalar fill example.
- Identify which resulting value violates the city's meaning.
Supply a mapping of column defaults
The direct answer to pandas fillna different values for different columns is a dictionary passed to DataFrame.fillna. Its keys are column names. The city key maps to 'Unknown'; the score key maps to 0. Each replacement applies only where that named column is missing. Existing values, including the Rome label and numeric four, remain as they were.
The call returns a new DataFrame by default, so a caller can inspect both versions. This is useful for data cleaning because the original record is evidence of what arrived. Avoid inplace=True unless there is a clear reason to discard that original state. For larger pipelines, make the fill mapping a named policy rather than scattered literals.
import pandas as pd
frame = pd.DataFrame({'city':[None,'Rome'], 'score':[4.0,None]})
fixed = frame.fillna({'city':'Unknown', 'score':0})
print(fixed['city'].tolist())
print(fixed['score'].tolist())['Unknown', 'Rome']
[4.0, 0.0]- Predict both output lists.
- Point to the dictionary key that controls each replacement.
Preserve untouched columns and audit the source
A mapping need not cover every column. Here note is intentionally absent from the fill mapping, so a missing note remains missing. That is often better than inventing a note that no one wrote. Verify with pd.isna instead of comparing a missing value with equality; NaN does not behave like an ordinary string or number in comparisons.
Also inspect the input after computing fixed. By default fillna did not mutate it, so its city is still missing. This makes it possible to compare raw and cleaned records or test the transformation. Filling unknown scores with zero may bias averages, so a production analysis must justify that rule; preserving missing scores can be the more honest choice when zero has a real measurement meaning.
import pandas as pd
frame = pd.DataFrame({'city':[None], 'score':[None], 'note':[None]})
fixed = frame.fillna({'city':'Unknown', 'score':0})
print(pd.isna(fixed.loc[0,'note']))
print(pd.isna(frame.loc[0,'city']))True
True- Check the note in the result.
- Check the city in the original and explain why retaining raw data helps.
Try it in Python
Edit the example and run it. Python starts in your browser the first time you click Run.
Python console
Ready to runNeed input()? Add one value per line
Your output appears here.
Need a hint?
Call frame.fillna with a dictionary whose keys are city and score; do not pass inplace=True.
Complete the task and select Check task to verify your code.
Quick quiz
Three questions. You can change your answers and try again.
Typical mistakes
Everyone meets these errors. See what causes them and how to fix them.
One scalar for mixed column types
frame.fillna(0)frame.fillna({'city': 'Unknown', 'score': 0})What happens: The city column gets a numeric zero instead of a meaningful label.
Choose replacements that match each field's meaning and type.
Confusing blank strings with missing data
frame.fillna({'city':'Unknown'})Normalize blank strings deliberately before fillna if the data contract calls for it.What happens: A city value of '' remains blank.
fillna operates on recognized null markers.