data visualization
matplotlib
python
plotting
multiple functions

How to plot multiple functions on the same figure

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

In Matplotlib, plotting multiple functions on the same figure usually means drawing several lines on the same axes before calling show(). The basic technique is simple, but a readable chart still depends on using labels, scales, and styling carefully.

The simplest pattern

If the functions share the same x values, call plot repeatedly:

python
1import numpy as np
2import matplotlib.pyplot as plt
3
4x = np.linspace(0, 2 * np.pi, 400)
5
6plt.plot(x, np.sin(x), label="sin(x)")
7plt.plot(x, np.cos(x), label="cos(x)")
8plt.plot(x, np.sin(x) + np.cos(x), label="sin(x) + cos(x)")
9
10plt.xlabel("x")
11plt.ylabel("y")
12plt.title("Three functions on one figure")
13plt.legend()
14plt.grid(True)
15plt.show()

Each plt.plot(...) call adds another line to the current axes. That is all you need for quick exploratory work.

Why the object-oriented API is often better

For anything beyond a tiny script, use the explicit fig, ax = plt.subplots() style. It makes it obvious which axes receive the data and avoids confusion when figures become more complex.

python
1import numpy as np
2import matplotlib.pyplot as plt
3
4x = np.linspace(-3, 3, 300)
5
6fig, ax = plt.subplots(figsize=(8, 5))
7ax.plot(x, x**2, label="x squared")
8ax.plot(x, x**3, label="x cubed")
9ax.plot(x, np.exp(x), label="exp(x)")
10
11ax.set_xlabel("x")
12ax.set_ylabel("value")
13ax.set_title("Multiple functions on one axes")
14ax.set_ylim(-10, 20)
15ax.grid(True, alpha=0.3)
16ax.legend()
17
18plt.tight_layout()
19plt.show()

The structure is clearer, especially when you later add subplots, twin axes, or custom formatting.

Make the lines distinguishable

Multiple functions become unreadable fast if they all look the same. Give each line a different style or color:

python
1import numpy as np
2import matplotlib.pyplot as plt
3
4x = np.linspace(0, 10, 200)
5
6plt.plot(x, np.sin(x), color="navy", linewidth=2, label="sin(x)")
7plt.plot(x, np.cos(x), color="darkred", linestyle="--", linewidth=2, label="cos(x)")
8plt.plot(x, np.sin(2 * x), color="darkgreen", linestyle=":", linewidth=2, label="sin(2x)")
9
10plt.legend()
11plt.show()

Labels matter just as much as line styles. Without a legend, the reader is forced to guess which curve is which.

When functions have very different scales

If one function is bounded and another grows quickly, the smaller one can look almost flat. In that case, either limit the plotted range or use a second axis.

python
1import numpy as np
2import matplotlib.pyplot as plt
3
4x = np.linspace(0, 4, 200)
5
6fig, ax1 = plt.subplots()
7ax1.plot(x, np.sin(x), color="blue", label="sin(x)")
8ax1.set_ylabel("sin(x)", color="blue")
9
10ax2 = ax1.twinx()
11ax2.plot(x, np.exp(x), color="orange", label="exp(x)")
12ax2.set_ylabel("exp(x)", color="orange")
13
14plt.title("Functions with different scales")
15plt.show()

Use this sparingly. Twin axes help with scale differences, but they can also make a chart harder to interpret if overused.

When not to overlay everything

Putting every function on one axes is not always the best choice. If you have many lines or very different shapes, subplots are often clearer:

python
1import numpy as np
2import matplotlib.pyplot as plt
3
4x = np.linspace(0, 2 * np.pi, 200)
5fig, axes = plt.subplots(1, 2, figsize=(10, 4))
6
7axes[0].plot(x, np.sin(x), label="sin(x)")
8axes[0].plot(x, np.cos(x), label="cos(x)")
9axes[0].legend()
10
11axes[1].plot(x, np.tan(x), label="tan(x)")
12axes[1].set_ylim(-5, 5)
13axes[1].legend()
14
15plt.tight_layout()
16plt.show()

The goal is not merely to fit everything onto one figure. The goal is to make the comparison easy to understand.

Common Pitfalls

One common mistake is calling plt.show() too early. Once the figure is shown and the script continues, later plot calls may affect a new figure rather than the one you intended.

Another issue is forgetting labels and legend(). When several lines use similar colors, the chart becomes ambiguous immediately.

Scale mismatch is another frequent problem. If one function has values around 1 and another has values around 1000, the smaller curve may appear invisible unless you adjust the range or use a second axis.

Finally, do not mix plt.plot and ax.plot casually in the same script unless you are certain which axes are active. The object-oriented style is safer for maintainable code.

Summary

  • Plot multiple functions on one figure by calling plot multiple times before show().
  • Prefer the object-oriented API for clearer, more maintainable plotting code.
  • Use labels, legends, and line styles to keep the figure readable.
  • Adjust axis limits or use twin axes when scales differ sharply.
  • Choose subplots instead of overlays when too many functions make one chart cluttered.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.