Chapter V — Python Libraries

Plotting Mathematical
Functions from Zero

A complete step-by-step guide to NumPy & Matplotlib for first-year mathematics students

🔢 NumPy arrays
📈 Line plots
🔵 Scatter plots
📊 Histograms
🎓 First-year level

This tutorial is structured as a progressive journey. Each section builds on the previous one.

Why use Python libraries to plot functions?

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.

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.5 5. 7.5 10.] 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:

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
import numpy as np # ── Example 1: Polynomial f(x) = x² on [-3, 3] ─────────────────── x_poly = np.linspace(-3, 3, 200) print("Polynomial x-axis:") print(" Start:", x_poly[0], " End:", x_poly[-1], " Points:", len(x_poly)) # ── Example 2: Trigonometric f(x) = sin(x) on [0, 2π] ──────────── x_trig = np.linspace(0, 2 * np.pi, 400) print("\nTrigonometric x-axis:") print(" Start:", round(x_trig[0], 4), " End:", round(x_trig[-1], 4)) # ── Example 3: Exponential f(x) = eˣ on [-2, 3] ────────────────── x_exp = np.linspace(-2, 3, 300) print("\nExponential x-axis:") print(" Start:", x_exp[0], " End:", x_exp[-1])
Output
Polynomial x-axis: Start: -3.0 End: 3.0 Points: 200 Trigonometric x-axis: Start: 0.0 End: 6.2832 Exponential x-axis: Start: -2.0 End: 3.0
Q
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)

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 values print("x values: ", list(round(v, 2) for v in x)) # ── f(x) = x² (quadratic) ─────────────────────────────────────────────── y1 = x**2 print("f(x) = x²: ", list(round(v, 2) for v in y1)) # ── f(x) = 2x + 1 (linear) ────────────────────────────────────────────── y2 = 2*x + 1 print("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))
Output
x values: [-3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0] f(x) = x²: [9.0, 4.0, 1.0, 0.0, 1.0, 4.0, 9.0] f(x)=2x+1: [-5.0, -3.0, -1.0, 1.0, 3.0, 5.0, 7.0] f(x)=sin(x):[-0.14, -0.91, -0.84, 0.0, 0.84, 0.91, 0.14] f(x) = eˣ: [0.05, 0.14, 0.37, 1.0, 2.72, 7.39, 20.09] f(x) = |x|: [3.0, 2.0, 1.0, 0.0, 1.0, 2.0, 3.0]
⚠️ 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.

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
import numpy as np import matplotlib.pyplot as plt # ── Plot 1: Quadratic f(x) = x² - 2x - 3 ─────────────────────────────── x1 = np.linspace(-2, 4, 300) y1 = x1**2 - 2*x1 - 3 plt.plot(x1, y1) plt.show() # ── Plot 2: Sine f(x) = sin(x) ────────────────────────────────────────── x2 = np.linspace(0, 2 * np.pi, 400) y2 = np.sin(x2) plt.plot(x2, y2) plt.show() # ── Plot 3: Exponential f(x) = eˣ ────────────────────────────────────── x3 = np.linspace(-2, 3, 300) y3 = np.exp(x3) plt.plot(x3, y3) plt.show()
Q
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

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
ParameterWhat it controlsCommon 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()

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 from to

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 01 Your 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 02 Comparing 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 03 One 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 04 Exponential 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 05 Piecewise 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()

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.