Before writing any code, let's understand what problem we are solving — and why Python libraries make it so much easier.
📐 Mathematical analogy
In mathematics, plotting f(x) = x² by hand means: choosing values of x, computing each y = x², marking each point (x, y) on graph paper, and connecting the dots. For 100 points this takes hours. Python does it in milliseconds.
❌ Without a library (manual)
# You must do everything by hand
x = -3
y = x**2 # = 9# mark point (-3, 9)
x = -2
y = x**2 # = 4# mark point (-2, 4)# ... repeat 100 more times# then draw by hand → takes hours
✅ With NumPy + Matplotlib
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3, 3, 300)
y = x**2
plt.plot(x, y)
plt.show()
# 300 points, plotted instantly ✓
💡Key idea: NumPy handles the numbers (creating x-values, computing y-values). Matplotlib handles the drawing (axes, curves, labels, colors). Together they replace hours of manual work.
Section 02
NumPy — the number engine
Before we plot anything, we need to understand the NumPy tools we'll use to create x-values and compute y-values.
🔢
The three essential NumPy functions for plotting
You will use these in every single plot you make
Function
What it does
Example
Output
np.linspace(a, b, n)
Creates n evenly spaced values between a and b — your x-axis
np.linspace(0, 1, 5)
[0, 0.25, 0.5, 0.75, 1]
np.arange(a, b, step)
Creates values from a to b with a given step — like Python's range but for arrays
np.arange(0, 10, 3)
[0, 3, 6, 9]
x**2, np.sin(x), …
Applies a mathematical operation to every element of x at once — your y-values
np.array([1,2,3])**2
[1, 4, 9]
🧠linspace vs arange: Use np.linspace when you know how many points you want (recommended for plotting). Use np.arange when you know the step size. For smooth curves, always use np.linspace with at least 200 points.
numpy_basics.py — understanding linspace
import numpy as np
# Create 5 evenly spaced values between 0 and 10
x_few = np.linspace(0, 10, 5)
print("5 points: ", x_few)
# Create 11 evenly spaced values between 0 and 10
x_more = np.linspace(0, 10, 11)
print("11 points: ", x_more)
# For plotting, we usually use 200-500 points
x_smooth = np.linspace(-5, 5, 300)
print("First 5 of 300:", x_smooth[:5])
print("Shape:", x_smooth.shape)
Output
5 points: [ 0.2.55.7.510.]
11 points: [ 0.1.2.3.4.5.6.7.8.9.10.]
First 5 of 300: [-5.-4.96655518-4.93311036-4.89966555-4.86622074]
Shape: (300,)
Why does the number of points matter? More points = smoother curve. See for yourself:
Section 03 — Step 1 of 3
Step 1 — Build your x-axis
To plot f(x), you need to decide: for which values of x? This is your domain — the x-axis of your plot.
f : [a, b] → ℝ
We choose the interval [a, b] where we want to study the function. NumPy will create all x-values inside this interval.
1
Choose your interval [a, b]
Decide the minimum and maximum x-value. Example: to study f(x) = sin(x) over one full period, choose [0, 2π] ≈ [0, 6.28].
2
Choose the number of points n
More points = smoother curve. For polynomials, 100–200 is enough. For oscillating functions like sin or cos, use 300–500.
3
Call np.linspace(a, b, n)
This creates a 1-D NumPy array of n equally spaced values from a to b. This array is your x-axis.
step1_x_axis.py — building the x-axis for different functions
You want to plot f(x) = x³ on the interval [−5, 5] with 250 points. Which call is correct?
Anp.arange(-5, 5, 250)
Bnp.linspace(-5, 5, 250)
Cnp.linspace(250, -5, 5)
Dnp.zeros(250)
✅ Correct! np.linspace(-5, 5, 250) creates exactly 250 equally spaced values from -5 to 5.
❌ Not quite. np.linspace(a, b, n) where a=start, b=end, n=number of points. So: np.linspace(-5, 5, 250).
Section 04 — Step 2 of 3
Step 2 — Compute the y-values
Once you have your x-array, computing y = f(x) is a single line of code. NumPy applies the function to every element simultaneously — this is called vectorized computation.
🧮 Mathematical parallel
If x = [1, 2, 3, 4] and f(x) = x², then in mathematics:
f(1)=1, f(2)=4, f(3)=9, f(4)=16 → y = [1, 4, 9, 16].
NumPy does this for 300 values with a single expression: y = x**2
step2_y_values.py — computing y from x for five different functions
import numpy as np
x = np.linspace(-3, 3, 7) # small array so we can see all valuesprint("x values: ", list(round(v, 2) for v in x))
# ── f(x) = x² (quadratic) ───────────────────────────────────────────────
y1 = x**2print("f(x) = x²: ", list(round(v, 2) for v in y1))
# ── f(x) = 2x + 1 (linear) ──────────────────────────────────────────────
y2 = 2*x + 1print("f(x)=2x+1: ", list(round(v, 2) for v in y2))
# ── f(x) = sin(x) (trigonometric) ───────────────────────────────────────
y3 = np.sin(x)
print("f(x)=sin(x):", list(round(v, 2) for v in y3))
# ── f(x) = eˣ (exponential) ─────────────────────────────────────────────
y4 = np.exp(x)
print("f(x) = eˣ: ", list(round(v, 2) for v in y4))
# ── f(x) = |x| (absolute value) ─────────────────────────────────────────
y5 = np.abs(x)
print("f(x) = |x|: ", list(round(v, 2) for v in y5))
⚠️Common mistake: Using Python's built-in math.sin() instead of np.sin(). The built-in math functions only work on a single number. NumPy functions work on entire arrays. Always use np.sin(), np.cos(), np.exp(), etc. when working with arrays.
Section 05 — Step 3 of 3
Step 3 — Draw the plot
Now you have x and y arrays. Pass them to Matplotlib and it draws the curve for you. This is the minimal working example — the skeleton of every plot you'll ever make.
⭐
The 7-line template — memorise this!
Every plot you will ever make follows this exact structure
minimal_plot.py — the complete template
# ── STEP 0: Import ───────────────────────────────────────────────────────import numpy as np
import matplotlib.pyplot as plt
# ── STEP 1: Build x-axis ─────────────────────────────────────────────────
x = np.linspace(-3, 3, 300) # 300 points from -3 to 3# ── STEP 2: Compute y-values ──────────────────────────────────────────────
y = x**2# f(x) = x²# ── STEP 3: Plot ─────────────────────────────────────────────────────────
plt.plot(x, y) # draw the curve
plt.show() # display the window
0
Import — always at the top
import numpy as np and import matplotlib.pyplot as plt are the two lines you write once at the beginning of every script. The aliases np and plt are universal conventions.
1
plt.plot(x, y) — the drawing call
Takes two arrays of the same length: x (horizontal positions) and y (vertical positions). Matplotlib connects the dots in order to form the curve.
2
plt.show() — display the figure
Opens a window with the plot. In Jupyter Notebook this is often optional (the plot appears automatically), but it's good practice to always include it.
three_functions.py — plotting three different function types
What is wrong with this code? plt.plot(y, x) (to plot f(x) = x²)
Aplt.plot doesn't accept two arguments
Bx and y are swapped — x must be the first argument (horizontal axis)
CNothing is wrong, both orders are equivalent
Dplt.plot requires 3 arguments minimum
✅ Correct! plt.plot(x, y) always means: x-coordinates first, y-coordinates second. Swapping them plots the function on its side.
❌ Not quite. The issue is the order: plt.plot(x, y) means horizontal=x, vertical=y. Writing plt.plot(y, x) puts y on the horizontal axis — the curve appears rotated 90°.
Section 06
Styling your plot — labels, colors, grid
A bare plot is useful for testing. A well-labeled plot is useful for mathematics. Always add a title, axis labels, and a grid when presenting your work.
styled_plot.py — complete professional plot of f(x) = sin(x)
import numpy as np
import matplotlib.pyplot as plt
# ── Data ─────────────────────────────────────────────────────────────────
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x)
# ── Plot with style options ───────────────────────────────────────────────
plt.plot(x, y,
color='royalblue', # line color
linewidth=2, # line thickness
linestyle='-', # '-' solid ':' dotted '--' dashed
label='f(x) = sin(x)'# text for the legend
)
# ── Labels and title ─────────────────────────────────────────────────────
plt.title('Graph of f(x) = sin(x)', fontsize=14, fontweight='bold')
plt.xlabel('x (radians)', fontsize=12)
plt.ylabel('f(x)', fontsize=12)
# ── Grid and legend ──────────────────────────────────────────────────────
plt.grid(True, linestyle='--', alpha=0.5) # dashed semi-transparent grid
plt.legend() # show the label# ── Zero lines (x-axis and y-axis) ───────────────────────────────────────
plt.axhline(y=0, color='black', linewidth=0.8) # horizontal axis
plt.axvline(x=0, color='black', linewidth=0.8) # vertical axis
plt.show()
🎨
Quick style reference
The most-used styling options
Parameter
What it controls
Common values
color=
Line color
'blue', 'red', 'green', 'orange', '#1a56db'
linewidth=
Line thickness in points
1 thin, 2 normal, 3 thick
linestyle=
Dash pattern of the line
'-' solid, '--' dashed, ':' dotted, '-.' dash-dot
label=
Text shown in the legend
'f(x) = sin(x)'
marker=
Symbol at each data point
'o' circle, 's' square, '^' triangle, '+' plus
alpha=
Transparency (0=invisible, 1=opaque)
0.5 for semi-transparent elements
Plotting multiple curves on the same axes
Simply call plt.plot() multiple times before plt.show(). Each call adds one curve.
multiple_curves.py — comparing sin, cos, and sin+cos
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2 * np.pi, 400)
# Three separate plt.plot() calls = three curves on the same axes
plt.plot(x, np.sin(x), color='royalblue', label='sin(x)', linewidth=2)
plt.plot(x, np.cos(x), color='tomato', label='cos(x)', linewidth=2)
plt.plot(x, np.sin(x)+np.cos(x), color='mediumseagreen',
label='sin(x)+cos(x)', linewidth=2, linestyle='--')
plt.title('Trigonometric Functions', fontsize=14, fontweight='bold')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.grid(True, linestyle='--', alpha=0.4)
plt.legend()
plt.axhline(0, color='black', linewidth=0.8)
plt.show()
Section 07
Library of mathematical functions
Here is a complete reference of mathematical functions from your first-year curriculum and how to write them in Python/NumPy.
Mathematical notation
Python code
Type
Notes
f(x) = ax + b
y = a*x + b
Linear
Replace a and b with numbers
f(x) = x²
y = x**2
Quadratic
** is the power operator in Python
f(x) = x³
y = x**3
Cubic
Odd power → symmetric about origin
f(x) = √x
y = np.sqrt(x)
Root
Domain: x ≥ 0. Use linspace(0, …)
f(x) = |x|
y = np.abs(x)
Absolute value
V-shape, vertex at origin
f(x) = sin(x)
y = np.sin(x)
Trigonometric
Period 2π ≈ 6.28. Use np.pi
f(x) = cos(x)
y = np.cos(x)
Trigonometric
cos(x) = sin(x + π/2)
f(x) = tan(x)
y = np.tan(x)
Trigonometric
Avoid x = π/2 + kπ (vertical asymptotes)
f(x) = eˣ
y = np.exp(x)
Exponential
e ≈ 2.718. Always positive
f(x) = ln(x)
y = np.log(x)
Logarithm
Domain: x > 0. np.log is natural log
f(x) = log₁₀(x)
y = np.log10(x)
Log base 10
log₁₀(x) = ln(x) / ln(10)
f(x) = 1/x
y = 1/x
Hyperbola
Avoid x = 0. Use two separate intervals
🔬 Interactive Function Explorer
Live Demo
Select any function and adjust the interval to see it plotted instantly.
x fromto
Section 08
Exercises — practice from zero
Complete these exercises in order. Each one builds on the previous. Write the code in Jupyter Notebook or any Python environment.
Exercise 01Your very first plot⭐ Beginner
Plot the function f(x) = x² on the interval [−4, 4].
Use at least 200 points. Add a title, x-label, y-label, and a grid.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-4, 4, 200)
y = x**2
plt.plot(x, y, color='royalblue', linewidth=2)
plt.title('f(x) = x²', fontsize=14)
plt.xlabel('x')
plt.ylabel('f(x)')
plt.grid(True, linestyle='--', alpha=0.5)
plt.show()
Exercise 02Comparing two polynomials⭐ Beginner
On the same axes, plot both f(x) = x² and g(x) = x³ − x on [−2, 2].
Use different colors. Add a legend so the reader knows which curve is which.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-2, 2, 300)
plt.plot(x, x**2, color='royalblue', linewidth=2, label='f(x) = x²')
plt.plot(x, x**3 - x, color='tomato', linewidth=2, label='g(x) = x³ - x')
plt.title('Comparing f and g', fontsize=14)
plt.xlabel('x'); plt.ylabel('y')
plt.axhline(0, color='black', linewidth=0.8)
plt.axvline(0, color='black', linewidth=0.8)
plt.grid(True, linestyle='--', alpha=0.4)
plt.legend()
plt.show()
Exercise 03One full period of sin and cos★★ Intermediate
Plot f(x) = sin(x) and g(x) = cos(x) over one full period [0, 2π].
Hint: Use np.pi for π. Mark the x-axis with multiples of π/2 using plt.xticks.
Add the zero line, grid, title, and legend.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2 * np.pi, 500)
plt.plot(x, np.sin(x), color='royalblue', linewidth=2, label='sin(x)')
plt.plot(x, np.cos(x), color='tomato', linewidth=2, label='cos(x)')
# Mark x-axis at multiples of π/2
plt.xticks(
[0, np.pi/2, np.pi, 3*np.pi/2, 2*np.pi],
['0', 'π/2', 'π', '3π/2', '2π']
)
plt.title('sin(x) and cos(x) over one period', fontsize=14)
plt.xlabel('x'); plt.ylabel('f(x)')
plt.axhline(0, color='black', linewidth=0.8)
plt.grid(True, linestyle='--', alpha=0.4)
plt.legend()
plt.show()
Exercise 04Exponential growth and decay★★ Intermediate
On the same axes, plot f(x) = eˣ and g(x) = e⁻ˣ on [−3, 3].
Observe: one grows, one decays. Use np.exp(x) and np.exp(-x).
Also plot h(x) = 1 (horizontal line) to mark their intersection point.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3, 3, 300)
plt.plot(x, np.exp(x), color='royalblue', linewidth=2, label='f(x) = eˣ')
plt.plot(x, np.exp(-x), color='tomato', linewidth=2, label='g(x) = e⁻ˣ')
plt.axhline(1, color='gray', linewidth=1.5, linestyle='--', label='h(x) = 1')
plt.title('Exponential Growth and Decay', fontsize=14)
plt.xlabel('x'); plt.ylabel('f(x)')
plt.ylim(0, 10) # limit y-axis so the plot looks nice
plt.grid(True, linestyle='--', alpha=0.4)
plt.legend()
plt.show()
Exercise 05Piecewise function★★★ Challenge
Plot the piecewise function defined by:
f(x) = { x² if x < 0
{ 2x + 1 if x ≥ 0
Plot on [−3, 3]. Hint: use np.where(condition, value_if_true, value_if_false).
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3, 3, 400)
# np.where(condition, value_if_true, value_if_false)
y = np.where(x < 0, # condition
x**2, # if x < 0 : use x²2*x + 1) # if x >= 0 : use 2x+1
plt.plot(x, y, color='purple', linewidth=2, label='Piecewise f(x)')
# Mark the transition point x=0 with a vertical dashed line
plt.axvline(0, color='gray', linewidth=1, linestyle=':', label='x = 0 (transition)')
plt.title('Piecewise Function', fontsize=14)
plt.xlabel('x'); plt.ylabel('f(x)')
plt.grid(True, linestyle='--', alpha=0.4)
plt.legend()
plt.show()
Section 09
Summary — The complete recipe
Every plot you will make this year follows this exact four-step recipe. Memorise it.
COMPLETE_TEMPLATE.py — copy this every time you start a new plot
# ════════════════════════════════════════════════════════════════════════# COMPLETE PLOTTING TEMPLATE — First Year Mathematics# ════════════════════════════════════════════════════════════════════════# STEP 0: Import (always at the top)import numpy as np
import matplotlib.pyplot as plt
# STEP 1: Build the x-axis (choose your interval and number of points)
x = np.linspace(START, END, NUM_POINTS) # ← change these three values# STEP 2: Compute y-values (apply your function)
y = YOUR_FUNCTION(x)# ← write your formula here# STEP 3: Draw the curve
plt.plot(x, y,
color='royalblue',
linewidth=2,
label='f(x) = ...'# ← describe your function
)
# STEP 4: Labels, grid, legend, display
plt.title('Graph of f(x) = ...', fontsize=14)
plt.xlabel('x')
plt.ylabel('f(x)')
plt.grid(True, linestyle='--', alpha=0.5)
plt.axhline(0, color='black', linewidth=0.8) # zero line
plt.legend()
plt.show()
📦
Import alias
np / plt
📏
x-axis function
np.linspace(a,b,n)
⚡
y-values
vectorized ops
🖼️
Draw command
plt.plot(x, y)
🏷️
Axis labels
xlabel / ylabel
📐
Grid
plt.grid(True)
🏁
Display
plt.show()
🔢
Points for smooth curve
≥ 200
🎓You are ready! With these four steps you can plot any mathematical function you will encounter in your first year of university mathematics. Every advanced plot is just this template with extra styling added.