PySpark fillna(): replace null values

PySpark fillna(value) (alias df.na.fill(value)) replaces null values in a DataFrame. Pass a single value to fill all compatible columns, or a dict to fill specific columns with different values. Use dropna() to remove rows containing nulls instead of filling them.

Fill per column

df.fillna({"age": 0, "city": "unknown"}) assigns a default per named column. A scalar such as df.fillna(0, subset=["age"]) limits filling to compatible columns in the subset. With a dictionary, the dictionary keys choose the columns and the subset argument is ignored.

Drop vs fill vs coalesce

dropna() removes rows with nulls; fillna() substitutes a value; coalesce(col1, col2) returns the first non-null across columns.

fillna, na.fill and targeting specific columns

df.fillna(value) and df.na.fill(value) are the same operation. Passing a bare value fills every column of a matching type, which is rarely what you want. Two safer forms exist: restrict with a subset, as in df.fillna(0, subset=['amount', 'qty']), or pass a dictionary that maps each column to its own replacement, df.fillna({'amount': 0, 'country': 'unknown'}). The dictionary form is usually the clearest because the intent is visible per column.

Type matching and values that are not really null

For scalar fills, columns with incompatible types are ignored: numeric zero does not fill a string column. A per-column dictionary makes the intended replacements explicit. Empty strings and literal text such as "NULL" or "N/A" are not SQL nulls, so fillna does not replace those strings. Numeric fill also replaces floating-point NaN; the example below demonstrates both NaN and null in a double column. Choose defaults based on meaning: a missing age is not necessarily zero. For statistical imputation, compute the statistic separately or evaluate Spark ML Imputer.

Decide what a missing value means
Inputfillna behaviorDecision
SQL null / Python NoneReplaced by a compatible defaultChoose a meaningful per-column value
Floating-point NaNReplaced by a numeric fillCheck whether a constant or imputation is appropriate
Empty string or text "NULL"Preserved as textNormalize explicitly if it means missing
A row with missing fieldsPreserved by fillnaUse dropna only when removing rows is intended

Example (PySpark)

from pyspark.sql import SparkSession

spark = SparkSession.builder.getOrCreate()
df = spark.createDataFrame([
    (1, None, "Delhi", float("nan")),
    (2, 30, None, None),
    (3, None, "", 2.5),
], "id INT, age INT, city STRING, score DOUBLE")

filled = df.fillna({"age": 0, "city": "unknown", "score": 0.0})
for row in filled.orderBy("id").collect():
    print(row.id, row.age, repr(row.city), row.score)

Null age and city values receive their named defaults. Both NaN and null scores become 0.0, while the empty city string remains empty. repr() makes that empty string visible. These defaults demonstrate behavior; choose domain-appropriate replacements for production data.

Run this example in the free online PySpark compiler

Expected output

1 0 'Delhi' 0.0
2 30 'unknown' 0.0
3 0 '' 2.5

Frequently asked questions

How do I replace null values in PySpark?

Use df.fillna(value) or df.na.fill(value). Pass a dict to fill specific columns with different defaults.

What is the difference between fillna and dropna in PySpark?

fillna substitutes a value for nulls; dropna removes rows that contain nulls entirely.

How do I get the first non-null value across columns?

Use coalesce(col1, col2, ...) from pyspark.sql.functions, which returns the first non-null value per row.

Open the free PySpark compiler · Data Engineering challenges · Data Engineering jobs

Further reading

Follow the PySpark course