Skip to content

← Reductions and dim step 4 of 7

Easy Primitives

Compute row means while ignoring NaNs

Jump to the task

When NaN marks a missing observation, calculate the mean using only the observations that are present:

import torch

x = torch.tensor([1., float("nan"), 3.])
print(x.mean().item())  # nan
print(x.nansum().item())  # 4.0
print(x.nanmean().item())  # 2.0

Ordinary sum and mean propagate NaNs in the values they reduce. nansum excludes NaNs from the sum. nanmean excludes them from both the sum and the count, giving (1 + 3) / 2 = 2 here.

Why replacing missing values with zero changes the answer

Replacing the NaN with zero and then calling mean gives (1 + 0 + 3) / 3. The denominator still counts the missing observation. That answers a different question: the mean after imputing zero, rather than the mean of the available observations.

An entirely missing row has no observations to average. nanmean returns NaN for that row. Returning zero would incorrectly turn missing information into a measured value.

Decide what NaN means in your data

Ignoring NaNs is appropriate when they intentionally mark missing values, such as a sensor dropout. If they came from invalid arithmetic during training, skipping them can hide the underlying problem. Check where they first appear with torch.isnan and inspect the calculation that produced them.

nanmean skips NaNs, not all nonfinite values. Positive and negative infinity are not treated as missing. Also, nan_to_num replaces infinities by default as well as NaNs, so it is not interchangeable with a NaN-aware reduction.

Your task

def mean_of_valid(x: torch.Tensor) -> torch.Tensor

The harness supplies rows of floating-point values containing finite numbers or NaNs. Return the mean over the last axis, excluding NaNs. The result has one value per row. Return NaN for an all-NaN row.

The harness represents NaNs as the string nan in test data and converts them to floating-point NaNs before calling your function. Your function receives a tensor, not strings.