Checkpoint: Scientific Computing
Reviewed & published by Brayan K
This checkpoint ties together the scientific-computing tools you just learned — masked arrays, FFT, interpolation, histograms, memory layout, ufunc methods, statistics, linear algebra, and NaN-aware functions — in one applied challenge.
Part of the free NumPy course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
You'll review each tool, build a full noisy-signal analysis from a runnable starter, and test yourself with a short quiz before moving on to the capstone.
What This Checkpoint Reviews
- Masked arrays and NaN-aware reductions
- FFT and the magnitude spectrum
- Interpolation and histograms
- Memory layout, strides, and ufunc methods
- Statistics: mean, std, percentile
- Linear algebra: solve, det, eig
1 Recap: Your Scientific Toolkit
Here is the whole arc in one place. Each tool solves one kind of problem; the skill is knowing which to reach for.
| Tool | Use it for | Key call |
|---|---|---|
| Masked arrays | Flag invalid/sentinel data | np.ma.masked_equal |
| FFT | Frequency content of a signal | np.fft.fft |
| Interpolation | Values between samples | np.interp |
| Histogram | Bin and count values | np.histogram |
| Memory layout | Speed and contiguity | arr.flags, arr.strides |
| ufunc methods | reduce / accumulate / outer / at | np.add.reduce |
| Statistics | Center, spread, percentiles | np.std, np.percentile |
| Linear algebra | Solve, factor, invert | np.linalg.solve |
| NaN-aware funcs | Reductions over missing data | np.nanmean |
import numpy as np
# Masked array mean ignoring -1
print(np.ma.masked_equal(np.array([4, -1, 8, -1, 6]), -1).mean()) # 6.0
# FFT bin 0 is the sum (DC component)
print(np.fft.fft(np.array([1.0, 2.0, 3.0, 4.0]))[0]) # (10+0j)
# Interpolate halfway
print(np.interp(2.5, [0, 5], [0, 100])) # 50.0
# Histogram: 5 bins need 6 edges
counts, edges = np.histogram(np.arange(10), bins=5)
print(len(counts), len(edges)) # 5 6
# NaN-aware sum
print(np.nansum(np.array([1.0, np.nan, 3.0]))) # 4.0
# ✅ Expected output:
# 6.0
# (10+0j)
# 50.0
# 5 6
# 4.02 Build Challenge: Analyse a Noisy Signal
You are handed a 1D signal with two missing readings recorded as NaN. Your job, in one workflow: (1) count and skip the missing values with NaN-aware functions, (2) compute robust mean, std, max, and min, (3) histogram the valid values into 4 bins, and (4) solve a small linear system. Start from the runnable starter and fill in the TODO lines.
import numpy as np
signal = np.array([5.0, 7.0, np.nan, 6.0, 8.0,
9.0, np.nan, 4.0, 6.0, 7.0])
# STEP 1: how many readings are missing? (provided)
print("missing:", np.isnan(signal).sum()) # 2
# STEP 2: robust stats — TODO: replace each None
mean_val = None # TODO: np.nanmean(signal)
std_val = None # TODO: np.nanstd(signal)
print("mean:", mean_val, "std:", std_val)
# STEP 3: histogram of the valid values — TODO
valid = signal[~np.isnan(signal)]
# counts, edges = np.histogram(valid, bins=4, range=(4, 9))
# print(counts)
# STEP 4: solve 2x + y = 8 ; x + 3y = 9 — TODO
# A = np.array([[2, 1], [1, 3]]); b = np.array([8, 9])
# print(np.linalg.solve(A, b))Expected: missing: 2, mean 6.5 / std 1.5, histogram [2 2 2 2], and the system solves to [3. 2.].
3 Stretch: Tie In the FFT
For extra practice, build a clean periodic signal, find its dominant frequency with rfft, and confirm the NaN-aware mean of a poisoned copy still works. This blends three of the checkpoint topics in a few lines.
import numpy as np
N = 16
n = np.arange(N)
clean = 2*np.sin(2*np.pi*2*n/N) # 2 cycles over 16 samples
mag = np.abs(np.fft.rfft(clean))
print("peak bin:", np.argmax(mag)) # 2
# Poison a copy and still get a real mean
poisoned = clean.copy()
poisoned[3] = np.nan
print("nanmean:", round(np.nanmean(poisoned), 4)) # -0.0943
# ✅ Expected output:
# peak bin: 2
# nanmean: -0.0943🎯 Your turn: put the module together
Real sensor data has bad values, and the wrong reflex is to delete them and lose the timestamps. This exercise keeps the row, masks the glitch, fills it from its neighbours and summarises what remains — three functions from this module on a five-element array, with the numbers printed so you can check each one by hand.
# 🎯 YOUR TURN — a sensor log with one bad reading. Mask it, fill the gap by
# interpolation, and summarise the good readings. Fill in the three ___ blanks.
import numpy as np
t = np.array([0, 1, 2, 3, 4]) # minutes
readings = np.array([12.0, 14.0, -999.0, 16.0, 20.0]) # -999 = sensor glitch
# 1) hide the sentinel value instead of deleting it
masked = np.ma.masked_equal(readings, ___)
# 👉 replace ___ with -999
print(f"mean of good readings: {masked.mean():.1f}")
# 2) estimate what the sensor would have read at t=2 from its neighbours
ok = readings != -999
filled = np.interp(___, t[ok], readings[ok])
# 👉 replace ___ with 2
print(f"interpolated at t=2: {filled:.1f}")
# 3) the 75th percentile of the good readings
p = np.percentile(readings[ok], ___)
# 👉 replace ___ with 75
print(f"75th percentile: {p:.1f}")
# ✅ Expected output:
# mean of good readings: 15.5
# interpolated at t=2: 15.0
# 75th percentile: 17.0📝 Checkpoint Quiz
Answer each in your head, then reveal to check.
NaN poisons any arithmetic it touches, so a normal reduction collapses to nan. Use np.nanmean(arr) (and the rest of the nan* family) to skip the missing values.
np.ma.masked_equal(arr, -999).mean() — the masked reduction ignores the sentinel positions automatically.
It is the sum of all the input samples — the signal's average level scaled by the number of samples. For [1, 2, 3, 4] it is 10+0j.
Six. n bins need n+1 boundaries, so len(edges) == len(counts) + 1.
solve is faster and numerically more stable; explicitly inverting a matrix wastes work and accumulates more rounding error.
Only the strides are swapped; no data is copied. That is why a transposed C-contiguous array becomes F-contiguous instead.
❓ Frequently Asked Questions
Checkpoint complete — scientific computing consolidated!
You combined masked arrays, NaN-aware reductions, histograms, statistics, and linear algebra into a single noisy-signal workflow, and you can explain when to reach for each tool. That is the full scientific-computing arc of the course.
Practice quiz
Why does arr.mean() return nan when one element is NaN, and what fixes it?
- It is a bug; restart Python
- NaN poisons any arithmetic it touches, so use np.nanmean to skip missing values
- mean only works on integers
- You must sort the array first
Answer: NaN poisons any arithmetic it touches, so use np.nanmean to skip missing values. A single NaN poisons a normal reduction, collapsing the result to nan. The np.nan* family (np.nanmean and friends) skips the missing values.
How do you mask every -999 sentinel in an array so it is ignored in the mean?
- np.ma.masked_equal(arr, -999).mean()
- arr[arr != -999].sort()
- np.nanmean(arr, -999)
- np.histogram(arr, -999)
Answer: np.ma.masked_equal(arr, -999).mean(). np.ma.masked_equal builds a masked array that flags the -999 positions, and the masked reduction ignores them automatically.
In an FFT result, what does bin 0 (the DC component) represent?
- The highest frequency in the signal
- Always zero
- The sum of all input samples (the average level scaled by sample count)
- The phase of the signal
Answer: The sum of all input samples (the average level scaled by sample count). Bin 0 is the sum of all input samples. For [1, 2, 3, 4] it is 10+0j — the signal's average level times the number of samples.
If np.histogram returns 5 counts, how many bin edges are there?
- 4
- 5
- 6
- 10
Answer: 6. n bins need n+1 boundaries, so len(edges) == len(counts) + 1. Five counts means six edges.
Why prefer np.linalg.solve(A, b) over np.linalg.inv(A) @ b?
- solve is faster and numerically more stable
- inv does not exist in NumPy
- They give different answers on purpose
- solve only works on 2x2 matrices
Answer: solve is faster and numerically more stable. solve is faster and more numerically stable. Explicitly inverting a matrix wastes work and accumulates more rounding error.
A transpose arr.T is instant even on huge arrays. What actually changes?
- All the data is copied in the background
- Only the strides are swapped; no data is copied
- The dtype changes to float
- The array is reloaded from disk
Answer: Only the strides are swapped; no data is copied. Transposing only swaps the strides, so no data moves. That is why a transposed C-contiguous array becomes F-contiguous instead.
Which function estimates a value between two known sample points?
- np.histogram
- np.interp
- np.fft.fft
- np.percentile
Answer: np.interp. np.interp does piecewise-linear interpolation. For example np.interp(2.5, [0, 5], [0, 100]) returns 50.0, halfway between the endpoints.
Which call computes the value below which a given percentage of the data falls?
- np.std
- np.percentile
- np.nansum
- np.interp
Answer: np.percentile. np.percentile(arr, q) returns the q-th percentile — the value below which q percent of the data lies. np.std measures spread, not position.
What does np.add.reduce(arr) do?
- Removes duplicate elements
- Sums all elements, like np.sum
- Returns the running cumulative sum
- Builds an outer product
Answer: Sums all elements, like np.sum. reduce is a ufunc method that folds the operation across the array, so np.add.reduce sums every element. np.add.accumulate would give the running sum.
Which function returns the sum of an array while treating NaN entries as zero?
- np.sum
- np.nansum
- np.cumsum
- np.add.outer
Answer: np.nansum. np.nansum ignores NaN values (treating them as 0). A plain np.sum would return NaN if any element is NaN.
Continue this course
- Previous: NaN-Aware Functions (nanmean, nansum)
- Next: Capstone: Image as an Array — Treat an image as a 3D array and manipulate its pixels
- Quick reference: NumPy cheat sheet
Frequently asked questions
What does this scientific computing checkpoint cover?
It pulls together the whole scientific-computing arc of the course: masked arrays for invalid data, the FFT for frequency analysis, np.interp for interpolation, np.histogram for binning, memory layout and strides, ufunc methods, descriptive statistics, np.linalg for linear algebra, and the NaN-aware functions. The build challenge asks you to clean a noisy signal, summarize it robustly, bin it, and solve a small linear system in one workflow.
Should I use a masked array or NaN functions for missing data?
Both ignore invalid values in reductions; the choice is about fit. Masked arrays keep a separate boolean mask, work with integer dtypes, and remember which values were invalid so you can recover them, which suits sentinel codes like -999. NaN functions (np.nanmean and friends) are lighter when your data is already float and the gaps are genuinely NaN. Many pipelines mix them: detect with np.isnan, then summarize with the nan* family.
How do I know I am ready to move past this checkpoint?
You should be able to take a messy 1D signal, count and skip its missing values, compute robust statistics with the nan* functions, bin the valid data with np.histogram, and solve a small system with np.linalg.solve — without looking up each call. If the build challenge below runs and you can explain every line, you are ready for the capstone.