Written and maintained by CASRAI Editorial Board
Last updated
A scatter plot in Python is drawn with matplotlib.pyplot.scatter or, with grouping built in, seaborn.scatterplot. Both place one point per observation, with one variable on each axis. This guide gives the install commands, a working example for each library, a side-by-side mapping of their size, colour and marker parameters, and how to read the result before you report a correlation.
What a scatter plot is used for in research
A scatter plot shows the relationship between two continuous variables, one point per case. Draw it before you compute a statistic: the shape of the cloud tells you whether a single summary number is appropriate. A correlation coefficient summarises only a straight-line pattern, so a curved or clustered cloud needs a different treatment. The same plot is the starting point for fitting a line (see regression analysis) and for checking the data before analysis alongside a histogram and descriptive statistics.
If your analysis is in R rather than Python, see scatterplots in R.
Install or access
Both libraries are installed from the Python Package Index with pip, according to their own installation pages (checked 2026-10-29).
- Matplotlib:
pip install matplotlib. The Matplotlib getting-started page also listsconda install -c conda-forge matplotlib,pixi add matplotlibanduv add matplotlib. - Seaborn:
pip install seaborn. The basic invocation installs seaborn and, if necessary, its mandatory dependencies, which are numpy, pandas and matplotlib. Seaborn can also be installed withconda install seaborn -c conda-forge. The seaborn installation page states a supported Python version of 3.8 or later.
Step by step: a scatter plot with Matplotlib
The Matplotlib getting-started page demonstrates the pattern fig, ax = plt.subplots(), a plotting call on ax, then plt.show(). Its example is a line plot; the version below applies the same pattern with ax.scatter.
- Import the plotting module:
import matplotlib.pyplot as plt - Prepare two sequences of equal length, one value per observation, for example
x = [1, 2, 3, 4, 5]andy = [2.1, 3.9, 6.2, 7.8, 10.1]. - Create the figure and axes:
fig, ax = plt.subplots() - Draw the points:
ax.scatter(x, y) - Display the figure:
plt.show()
The documented signature is matplotlib.pyplot.scatter(x, y, s=None, c=None, *, marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=None, linewidths=None, edgecolors=None, colorizer=None, plotnonfinite=False, data=None, **kwargs). The x and y arguments are “float or array-like, shape (n, )”, the data positions.
Marker size and colour in plt.scatter
sis the marker size in points**2 (typographic points are 1/72 in.). The default isrcParams['lines.markersize'] ** 2. Because it is an area, doublingsdoes not double the marker width.csets the marker colours. Accepted values are a scalar or sequence of n numbers mapped to colours usingcmapandnorm; a 2D array whose rows are RGB or RGBA; a sequence of colours of length n; or a single colour format string.
Step by step: a grouped scatter plot with Seaborn
Seaborn’s scatterplot takes a table and column names, and can map a third variable to colour, size or marker. The first example in the seaborn documentation uses its bundled tips data set: tips = sns.load_dataset("tips") followed by sns.scatterplot(data=tips, x="total_bill", y="tip"). The steps below use a small table built in your own script instead.
- Import the libraries:
import pandas as pd,import seaborn as snsandimport matplotlib.pyplot as plt - Build a table with one row per observation, for example
df = pd.DataFrame({"dose": [1, 2, 3, 4, 5, 6], "response": [2.0, 3.1, 4.2, 4.8, 6.1, 7.2], "group": ["A", "A", "A", "B", "B", "B"]}) - Draw the points, colouring by group:
sns.scatterplot(data=df, x="dose", y="response", hue="group") - Display the figure:
plt.show()
The documented signature is seaborn.scatterplot(data=None, *, x=None, y=None, hue=None, size=None, style=None, palette=None, hue_order=None, hue_norm=None, sizes=None, size_order=None, size_norm=None, markers=True, style_order=None, legend='auto', ax=None, **kwargs). Its hue argument is a grouping variable that produces points with different colours, size produces points with different sizes, and style produces points with different markers. Numeric values passed to style are always treated as categorical.
How the two libraries’ parameters line up
| Purpose | matplotlib.pyplot.scatter | seaborn.scatterplot |
|---|---|---|
| Point positions | x, y: array-like, shape (n, ) |
x, y: vectors or keys in data |
| Marker size | s: size in points**2 |
size: grouping variable; sizes controls the size range |
| Colour | c with cmap and norm |
hue grouping variable, with palette, hue_order, hue_norm |
| Marker shape | marker |
style grouping variable, with markers and style_order |
| Draw on an existing axes | Call ax.scatter on that axes |
ax |
The practical difference follows from the signatures: in Matplotlib you pass the sizes or colours yourself, while in Seaborn you name a column and the library assigns the visual encoding and, with legend='auto', builds the legend.
Output and how to read it
Look at four things before you quote any statistic.
- Form. Do the points follow a straight line, a curve or no pattern? A straight-line summary such as Pearson’s r is only meaningful for the first.
- Direction. Points rising from left to right indicate a positive association; falling points a negative one.
- Spread. A tight band means observations sit close to the pattern; a wide cloud means they do not.
- Outliers and groups. Isolated points, or separate clusters, can change a summary statistic. If a categorical variable explains the clusters, map it to
hueorstylein Seaborn. For checking distribution shape, see Q-Q plots.
For fitting a line to the points, the linear regression calculator guide explains the quantities involved. For figure layout in publications, see designing effective scientific figures.
Troubleshooting
The figure does not appear
The Matplotlib getting-started page tells readers whose plot does not show up to consult its Troubleshooting section. One documented cause is the backend: Matplotlib tries MacOSX, QtAgg, GTK4Agg, Gtk3Agg, TkAgg, WxAgg and then Agg, using the first usable one. Agg is a non-interactive backend that can only write to files, and it is used on Linux if Matplotlib cannot connect to an X display or a Wayland display. On a server or a remote session without a display, no window will open.
A single colour passed to c is rejected or ignored
The documentation warns that c should not be a single numeric RGB or RGBA sequence. To give every point one colour, pass a 2D array with a single row, or a colour format string.
Seaborn reports an import or version error
Install with pip install seaborn into the same environment that runs your script. The installation page notes that invoking pip as python -m pip install seaborn can avoid problems with which Python the pip command belongs to.
Free alternatives
Matplotlib and Seaborn are the two libraries documented above. Seaborn builds on Matplotlib, so the two can be combined: the ax argument of seaborn.scatterplot draws on an axes you created with plt.subplots().
| Library | Scatter function | Install | Best documented for |
|---|---|---|---|
| Matplotlib | matplotlib.pyplot.scatter |
pip install matplotlib |
Explicit control of size (s) and colour (c, cmap) |
| Seaborn | seaborn.scatterplot |
pip install seaborn |
Mapping table columns to colour, size and marker with hue, size, style |
FAQ
What is the simplest way to make a scatter plot in Python?
Install Matplotlib, create axes with fig, ax = plt.subplots(), call ax.scatter(x, y) with two equal-length sequences, and finish with plt.show().
How do I colour points by group?
In Seaborn, pass the grouping column to hue: sns.scatterplot(data=df, x="dose", y="response", hue="group"). In Matplotlib, pass a sequence of colours of length n, or numbers mapped through cmap, to c.
What units does the s argument use?
Marker size in points**2, where a typographic point is 1/72 in.
Should I draw the scatter plot before computing a correlation?
Yes. The plot shows whether the relationship is roughly linear and whether outliers or subgroups are present, which determines whether a single coefficient is a fair summary.
Sources
- Matplotlib documentation, matplotlib.pyplot.scatter (checked 2026-10-29).
- Matplotlib documentation, Getting started (checked 2026-10-29).
- Matplotlib documentation, Backends (checked 2026-10-29).
- Seaborn documentation, seaborn.scatterplot (checked 2026-10-29).
- Seaborn documentation, Installing and getting started (checked 2026-10-29).








