Corners
Linear interpolation leaves a corner at every inner point, where the slope jumps. In the chain of lesson 1.6.1 it jumps from 2 to at . Many quantities change smoothly, so a corner is usually a fault of the method, not a feature of the data.
The slope of a curve at a point is how steeply it climbs there. Measure it with a very short chord, the straight line joining two nearby points of the curve: its rise over run, as in lesson 1.2.1. Lesson 2.2.1 makes this exact.
A corner is a point where the slope just to the left and the slope just to the right disagree.
One polynomial through every point
A tempting fix is one polynomial through all the points, which has no corners anywhere. Through points with different values there is exactly one polynomial of degree at most .
For 2 points it is a line, and for 3 a parabola. np.polyfit(xs, ys, n - 1) finds it.
It usually wiggles. Take the S-shaped curve , which climbs from 0 to 4 around . Sample it at the 13 whole numbers from 0 to 12, and fit the polynomial of degree 12 through them.
Every data point lies between 0 and 4, yet the polynomial dips to near and rises to 4.514 near . To pass through every point it must turn many times, and the turns grow near the ends. More points make it worse, not better:
| points | 7 | 9 | 13 | 17 |
|---|---|---|---|---|
| polynomial, worst error | 0.297 | 0.329 | 0.515 | 0.918 |
| cubic spline, worst error | 0.21 | 0.09 | 0.0181 | 0.0044 |
The worst error is the largest gap between the estimate and the true curve. The cubic spline, built in the next section, does the opposite: each extra point brings it closer.
Three ways through the same 13 points. The chain of lines has corners, the cubic spline is smooth, and the one polynomial swings outside the range of the data near both ends.
Try it
The curve is sampled with 7, 9, 13 and 17 points between 0 and 12. Each line prints the number of points, then the worst error of the polynomial and of the spline, checked at 12,001 inputs.
The last line is the 13-point polynomial's lowest and highest values, and where they occur.
Cubic splines
A cubic spline keeps the low degree of linear interpolation but drops the corners. It joins each pair of neighbouring points with its own cubic, a polynomial of degree 3 (lesson 1.3.1). The cubics are chosen so that they meet smoothly.
Rule: Cubic spline
With points there are gaps, so cubics. SciPy's CubicSpline(xs, ys) finds them, and the result is called like a function.
A worked example: the tent. The points , and make a tent. Linear interpolation gives two straight pieces with a sharp corner at the top. The natural spline (defined below) uses two cubics: on the first gap it is , and the second is its mirror image.
By algebra, and , so the piece passes through both of its points. At the middle of the gap, . The table compares the spline with the straight piece.
| 0 | 0.25 | 0.5 | 0.75 | 1 | |
|---|---|---|---|---|---|
| straight piece | 0 | 0.25 | 0.5 | 0.75 | 1 |
| spline | 0 | 0.3672 | 0.6875 | 0.9141 | 1 |
The spline bulges above the straight piece and rounds off the top of the tent.
Try it
spline.c[:, 0] holds the first piece's coefficients, highest power first, as in lesson 1.3.1. They read .
The loop prints the table: the straight piece from np.interp, then the spline.
What "smooth" means at a join
At the two straight pieces have slopes 1 and , so the slope jumps by : that is the corner. For the spline, take short chords on each side of 1. With a run of 0.01 their slopes are 0.01495 on the left and on the right.
With a run of 0.001 they are 0.0015 and . Both sides settle on the same slope, 0, so the spline crosses the top of the tent level, with no corner.
The tent two ways. The straight pieces meet at a corner, where the slope jumps from 1 to . The spline is level at the top from both sides.
Bend is how fast the slope itself changes. At the top of the tent the spline bends downwards, like a cap; a curve that bends upwards looks like a cup. A spline also matches the bend at each join, so the curve never switches suddenly from turning gently to turning sharply.
So "smooth" at a join means no jump in slope and no jump in bend. SciPy reports both: spline(x, 1) is the slope at and spline(x, 2) the bend. Lessons 2.2.2 and 2.4.2 name them the derivative and the second derivative.
Try it
chords returns the slopes of the chords just left and just right of , with run . The straight pieces give 1 and ; the spline's chords close in on 0.
The third line is the spline's slope at 1, then its bend just left and just right of 1: both . The last line is its bend at the two ends, both 0.
End conditions
Count what a spline must satisfy: with points there are cubics of 4 coefficients each. Passing through its two points fixes 2 of each cubic's 4. Matching slope and bend fixes 2 more at each of the inner joins.
| points | 3 | 4 | 5 | 10 |
|---|---|---|---|---|
| coefficients, | 8 | 12 | 16 | 36 |
| through the points, | 4 | 6 | 8 | 18 |
| smooth joins, | 2 | 4 | 6 | 16 |
| still free | 2 | 2 | 2 | 2 |
Two conditions are always missing, one for each end, where a piece has no neighbour to match. This choice is the end condition. It changes the curve, most of all near the ends.
- Natural: the bend is 0 at both ends, so the curve runs straight as it leaves the data. Write
bc_type="natural". - Not-a-knot, SciPy's default: the first two pieces are one and the same cubic, and so are the last two.
- Clamped: the slope at each end is fixed;
bc_type="clamped"sets it to 0.
Rule: Natural spline
The two missing conditions are spent on making the curve straight where the data stop. It suits a curve that really does level off or straighten out at its ends.
For the tent, the natural spline gives 0.6875 at 0.5 and the default gives 0.75. With only 3 points the default's two pieces are one parabola, . Both pass through all three points.
The right choice depends on the curve. Sample at 0, 1, …, 5. It bends sharply near 0, so forcing a straight end there costs accuracy: the natural spline's worst error is 0.5851, the default's 0.2785.
Try it
The first line is the tent at 0.5, natural then default.
Then the two end conditions on sampled at 0 to 5, each with its worst error over 501 inputs.
Splines against straight lines
On smooth data a spline is usually far more accurate. For at 0 to 5, linear interpolation's worst error is 0.8578 and the default spline's 0.2785, about three times smaller.
A spline has three costs that straight lines do not.
- It depends on every point. Raising the point at 4 by 0.1 moves the spline by at 2.5, a gap away. The straight lines there do not move; case study 1.6.4 meets this with a bad quote.
- It runs away outside the data. Past the last point
CubicSplinekeeps using the last cubic. It gives 0.6556 at 7, where the true value is 1.25, and at 8, although is never negative. Passextrapolate=Falseto getnaninstead. - It can overshoot, as the next section shows.
Try it
The first line is the worst error of np.interp, then of the spline.
Next come the spline's values at 7 and 8 beside the true ones, and the change at 2.5 after raising one point, spline then lines. The last line refuses to extrapolate.
Overshoot
To avoid corners, a spline may swing above or below the data. Take the points , , and , a step up. The natural spline through them dips to about and rises to about 1.128, outside the range of the data.
That matters when values must stay within limits, such as a quantity that cannot be negative. Linear interpolation is then safer: between two points it stays between their values, as lesson 1.6.1 showed. SciPy also has splines built to keep the shape of the data, such as PchipInterpolator.
Try it
The plot compares both methods on the step. The spline is smooth but overshoots at both ends of the rise; the straight pieces never leave the range of the data.
The printed numbers are the spline's lowest and highest values over 301 inputs.
Common mistakes
- A higher degree is not a better fit. One polynomial through many points wiggles, and more points make it worse.
- No gaps is not the same as smooth. The chain of lines has no gaps, but its slope jumps at every corner. Smooth means no jump in slope or in bend.
- The end condition changes the answer, most of all near the ends: 0.6875 against 0.75 for the tent.
- A spline can overshoot. Use linear interpolation when values must stay inside the data's range.
- Never trust a spline outside the data. Its last cubic runs away: at 8 for a curve that is never negative.
- One point moves the whole spline. A bad data point spreads into neighbouring gaps; with straight lines it stays in its own two.
Cubic splines
0 of 11 correct
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
How to type answers
- Powers with
^:x^7,2^(1/3),a^-2. - Multiply with
*or by writing side by side:3x^2,2(x+1). ln(x)is the natural log,log(x, 2)is log base 2,eis Euler's number,sqrt(x)is a square root.sin(x),cos(x)andtan(x)take radians; writepifor π andsin(x)^2for sin²x.- Your first answer to each question is saved: it counts towards your score and brings the question back for review.
- Exact answers like
ln(20)/ln(3)are best. Decimals need about 4 significant figures.
Summary card
- One polynomial through many points wiggles near the ends, and more points make it worse.
- A cubic spline uses one cubic per gap, through both of its points, with no jump in slope or bend at any join.
- The slope is how steeply the curve climbs; the bend is how fast the slope changes.
- Two end conditions complete a spline. Natural: bend 0 at both ends. SciPy's default, not-a-knot: the first two pieces are one cubic, and so are the last two.
CubicSpline(xs, ys)builds it; call the result like a function, withbc_type="natural"for a natural spline.- Splines are usually far more accurate on smooth data. But they can overshoot, every point affects every piece, and they run away outside the data.