06 · Plotting & Visualization Basics¶
MATLAB's plotting is one of its strongest, most heavily used features —
built-in, fast, and designed so a single plot() call produces a usable
figure with almost no configuration.
The basic plot()¶
This opens a Figure window showing a smooth sine curve. x and y
must be the same length — plot() connects them point by point in order.
Nothing is printed to the Command Window; the output is entirely visual.
Labels, title, and grid — always add these¶
A plot without axis labels is close to useless for anyone but the person who made it five minutes ago:
x = 0:0.1:2*pi;
y = sin(x);
plot(x, y)
xlabel('x (radians)')
ylabel('sin(x)')
title('Sine Wave')
grid on
grid on overlays light gridlines, which make it much easier to read
values off the curve. These four lines — plot, xlabel, ylabel,
title (plus usually grid on) — are the baseline for almost every
MATLAB plot you'll make.
Multiple lines on one plot¶
x = 0:0.1:2*pi;
plot(x, sin(x), x, cos(x))
legend('sin(x)', 'cos(x)')
xlabel('x')
ylabel('y')
title('Sine and Cosine')
Passing multiple x, y pairs to one plot() call draws them all on the
same axes, each with a different default color, and legend() labels them
in the order they were plotted.
hold on is the alternative approach — useful when the curves come from
separate plot() calls (e.g. inside a loop) rather than one call:
plot(x, sin(x))
hold on % keep the current plot; don't erase it for the next one
plot(x, cos(x))
hold off % (optional) return to default overwrite behavior
legend('sin(x)', 'cos(x)')
Forgetting hold on
Without hold on, each new plot() call erases the previous
figure content and starts fresh — a very common beginner mistake when
trying to build up a chart across multiple calls or a loop, where only
the last curve ends up visible.
Line styles, colors, and markers¶
A short format string as the third argument to plot() controls
appearance:
plot(x, sin(x), 'r--') % red dashed line
plot(x, sin(x), 'g-o') % green solid line with circle markers
plot(x, sin(x), 'b:', 'LineWidth', 2) % blue dotted, thicker line (name-value pair)
| Code | Meaning | Code | Meaning |
|---|---|---|---|
r |
red | - |
solid line |
g |
green | -- |
dashed line |
b |
blue | : |
dotted line |
k |
black | -. |
dash-dot line |
o |
circle marker | x |
x marker |
Format-string characters can combine freely ('r--o' = red, dashed, with
circle markers); properties that don't have a short code, like LineWidth
or MarkerSize, are set as trailing 'Name', value pairs.
Scatter plots¶
scatter() is the right choice for unconnected, discrete data points —
where drawing a line between them (as plot does) would misleadingly imply
an ordering or trend:
hours_studied = [1, 2, 3, 4, 5, 6, 7, 8];
exam_score = [52, 58, 63, 70, 74, 82, 88, 91];
scatter(hours_studied, exam_score, 'filled')
xlabel('Hours Studied')
ylabel('Exam Score')
title('Study Time vs. Score')
grid on
Bar charts and histograms¶
categories = {'Q1', 'Q2', 'Q3', 'Q4'};
revenue = [120, 150, 90, 200];
bar(revenue)
set(gca, 'XTickLabel', categories) % label the bars with category names
ylabel('Revenue ($k)')
title('Quarterly Revenue')
bar() is for a small number of discrete categories with known values.
histogram() is different: it takes a set of raw, possibly-many
observations and automatically bins them, showing you the underlying
distribution:
data = randn(1, 1000); % 1000 random values from a standard normal distribution
histogram(data)
xlabel('Value')
ylabel('Count')
title('Distribution of Random Data')
Multiple plots in one figure: subplot¶
x = 0:0.1:2*pi;
subplot(2, 1, 1) % 2 rows, 1 column, this is plot #1
plot(x, sin(x))
title('Sine')
subplot(2, 1, 2) % 2 rows, 1 column, this is plot #2
plot(x, cos(x))
title('Cosine')
subplot(rows, cols, index) divides the current figure into a grid and
selects one cell to draw into next; index counts left-to-right,
top-to-bottom, same convention as reading English text.
Saving a figure to a file¶
plot(x, sin(x))
xlabel('x'); ylabel('sin(x)'); title('Sine Wave')
saveas(gcf, 'sine_wave.png') % gcf = "get current figure"
saveas infers the file format from the extension (.png, .jpg, .pdf,
.fig for MATLAB's own editable format, etc.). exportgraphics(gcf,
'sine_wave.png', 'Resolution', 300) is the more modern, higher-quality
alternative when you need print-resolution output.
New vs. reused figures¶
figure % opens a brand-new figure window
plot(x, sin(x))
figure % opens ANOTHER new window, doesn't touch the first
plot(x, cos(x))
Without an explicit figure call, MATLAB reuses the current figure window
(and, per the hold on/hold off rule above, overwrites its contents by
default) — call figure explicitly whenever you want a fresh, separate
window.
Plotting cheat sheet¶
| Task | Function |
|---|---|
| Line plot | plot(x, y) |
| Scatter (unconnected points) | scatter(x, y) |
| Bar chart (categories) | bar(values) |
| Histogram (distribution of raw data) | histogram(data) |
| Axis labels / title | xlabel(), ylabel(), title() |
| Multiple series, one legend | legend('name1', 'name2') |
| Keep adding to same axes | hold on / hold off |
| Gridlines | grid on |
| New figure window | figure |
| Multiple plots, one figure | subplot(rows, cols, index) |
| Save to file | saveas(gcf, 'name.png') |
How It Actually Works¶
Every plot() call builds an in-memory graphics object tree, not an
image: calling plot(x,y) creates (or reuses) a Figure object, which
contains an Axes object, which contains a Line object holding your
x/y data plus style properties (Color, LineWidth, Marker, …).
Nothing is rasterized to pixels until the rendering pipeline actually
needs to paint the screen or export a file — this is why you can grab a
handle (h = plot(x,y)) and change h.Color after the plot has already
"appeared": you're mutating a live object in the graphics tree, and
MATLAB's renderer redraws from that tree, not from a frozen bitmap.
hold on doesn't change how plotting math works — it flips a property
(NextPlot) on the current Axes object from 'replace' to 'add',
telling subsequent plotting commands to append new graphics-object
children to the existing axes instead of deleting the old ones first.
Axis limits (xlim, ylim) are computed automatically by default via a
"tight to data, then padded" heuristic that re-runs every time a child
object is added or removed, unless you pin them manually — which is why
adding a second plot() call to the same axes can silently rescale your
first curve's apparent shape as the axes auto-fit both datasets.
Rendering itself goes through one of two backends: the OpenGL-accelerated
renderer (default for anything with transparency, lighting, or many
points) or the software painters renderer (default for simple 2D vector
content, and what's used when exporting to vector formats like PDF/EPS so
lines stay crisp rather than being rasterized).
Note: describes MATLAB's documented graphics-object model; there is no MATLAB installation in this environment to render an actual figure.
🔀 See this in another language¶
Exercise¶
Create x = linspace(0, 10, 100) and plot y1 = x.^2 and y2 = 10*x on
the same axes using hold on, with a legend distinguishing the two curves,
axis labels, a title, and grid on. Then use subplot to create a 1×2
figure: the left panel showing your line plot from above, and the right
panel showing a histogram of 500 values from randn(1, 500). Save the
full figure to exercise_plot.png using saveas.