LESSON 164 · PRACTICAL PYTHON28 min

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

Read the video transcript

Select a timestamp to watch that moment on YouTube.

  1. 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

  2. 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.

  3. 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.

  4. 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.

  5. 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

  6. 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.

  7. 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.

  8. 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

  9. 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

PYTHON
import pandas as pd
frame = pd.DataFrame({'city':[None], 'score':[None]})
print(frame.fillna(0).loc[0].tolist())
EXPECTED OUTPUT
[0, 0]

A numeric zero in a city field does not mean unknown city.

02. Fill two columns differently

PYTHON
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())
EXPECTED OUTPUT
['Unknown', 'Rome']
[4.0, 0.0]

The mapping applies only the named default to each column.

03. Keep unrelated missing data and original input

PYTHON
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']))
EXPECTED OUTPUT
True
True

The 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.

01 / 03

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.

PYTHON
import pandas as pd
frame = pd.DataFrame({'city':[None], 'score':[None]})
print(frame.fillna(0).loc[0].tolist())
EXPECTED OUTPUT
[0, 0]
Follow the reasoning
  1. Run the scalar fill example.
  2. Identify which resulting value violates the city's meaning.
02 / 03

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.

PYTHON
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())
EXPECTED OUTPUT
['Unknown', 'Rome']
[4.0, 0.0]
Follow the reasoning
  1. Predict both output lists.
  2. Point to the dictionary key that controls each replacement.
03 / 03

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.

PYTHON
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']))
EXPECTED OUTPUT
True
True
Follow the reasoning
  1. Check the note in the result.
  2. 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 run
Need input()? Add one value per line
Ctrl / ⌘ + Enter to run
OUTPUT
Your output appears here.
Your turnImplement fill_missing(frame) using pandas fillna with different values: city becomes 'Unknown' and score becomes 0. Leave missing note values missing, and do not mutate the input. The sample should print ['Oslo', 'Unknown'] [4.0, 0.0].
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.

    01.How does fillna choose a different replacement per column?

    02.Does fillna replace an empty string automatically?

    03.What happens to a column absent from the fill mapping?

    Typical mistakes

    Everyone meets these errors. See what causes them and how to fix them.

    One scalar for mixed column types

    COMMON MISTAKE
    frame.fillna(0)
    FIX
    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

    COMMON MISTAKE
    frame.fillna({'city':'Unknown'})
    FIX
    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.

    Browse this lesson’s problem fixes

    Sources and further reading