Creatinga scatter plot in R is a fundamental skill for anyone working with data visualization, whether you are exploring relationships between two continuous variables, checking assumptions before modeling, or presenting results to an audience. This guide walks you through the entire process—from preparing your data to polishing a publication‑ready graphic—using base R, the powerful ggplot2 package, and an optional interactive approach with plotly. By the end, you will be able to produce clear, informative scatter plots meant for your specific analytical needs The details matter here..
Introduction
A scatter plot displays individual data points on a two‑dimensional plane, with one variable mapped to the x‑axis and another to the y‑axis. In R, you can generate scatter plots quickly with a few lines of code, but mastering the nuances—such as adjusting aesthetics, adding fit lines, and faceting by groups—will elevate your visual storytelling. The pattern of points reveals correlations, outliers, and clusters that might be hidden in tabular form. The main keyword for this tutorial is how to draw a scatter plot in R, and we will naturally incorporate related terms like base R graphics, ggplot2 scatter plot, customizing point aesthetics, and interactive scatter plot throughout the discussion.
Preparing Your Data
Before any plotting begins, ensure your data is in a tidy format, preferably a data frame where each column represents a variable and each row an observation. Common steps include:
- Importing data – use
read.csv(),read_excel(), orreadRDS()depending on the source. - Checking structure –
str(df)andhead(df)reveal column types and missing values. - Handling missing values – decide whether to remove (
na.omit(df)) or impute missing entries, as most plotting functions will drop NA rows silently. - Creating or transforming variables – you might need (e.g., log‑transforming skewed data with
log(df$variable)).
For illustration, we will use the built‑in mtcars dataset, which contains measurements for 32 automobiles:
data(mtcars) # loads the dataset
head(mtcars) # preview first six rows
The variables wt (weight) and mpg (miles per gallon) serve as a classic example of a negative correlation suitable for a scatter plot Simple, but easy to overlook..
Basic Scatter Plot with Base R
R’s base graphics system provides a quick way to draw a scatter plot using the plot() function. The simplest call looks like this:
plot(mtcars$wt, mtcars$mpg,
main = "Scatter Plot of Weight vs. MPG",
xlab = "Weight (1000 lbs)",
ylab = "Miles per Gallon",
pch = 19, # solid circle points
col = "steelblue")
Explanation of arguments
mtcars$wtandmtcars$mpgsupply the x and y coordinates.main,xlab, andylabset the title and axis labels.pchchooses the point character;19yields a clean andcolsets an open circle, 19 a solid circle).coldefines the point color; you can use named colors, hex codes, or RGB values.
Running the code produces a plain scatter plot that immediately shows the downward trend: heavier cars tend to have lower fuel efficiency.
Adding a Regression Line
To highlight the linear relationship, overlay a least‑squares fit line with abline():
fit <- lm(mpg ~ wt, data = mtcars) # fit linear model
abline(fit, col = "darkred", lwd = 2) # lwd controls line thickness
The lm() function creates a linear model object; abline() extracts its intercept and slope to draw the line. Adjusting lwd (line width) and col helps the line stand out against the points.
Changing Point Shapes by a Categorical Variable
If you want to encode a third variable—say, the number of cylinders (cyl)—you can map it to point shape or color:
# Convert cyl to a factor for discrete mapping
mtcars$cyl_f <- factor(mtcars$cyl)
plot(mtcars$wt, mtcars$mpg,
main = "Weight vs. MPG by Cylinder Count",
xlab = "Weight (1000 lbs)",
ylab = "Miles per Gallon",
pch = as.numeric(mtcars$cyl_f), # 1,2,3 → different shapes
col = as.
Here, `as.numeric()` transforms the factor levels into integers that `pch` and `col` interpret as distinct shapes and colors. The `legend()` call adds a key for interpretation.
## Enhancing the Plot with ggplot2
While base R graphics are serviceable, **ggplot2**—part of the tidyverse—offers a more flexible, layer‑based grammar of graphics. It simplifies complex customizations and produces aesthetically pleasing defaults.
### Installing and Loading ggplot2
If you have not installed the package yet, run:
```r
install.packages("ggplot2")
library(ggplot2)
Basic ggplot2 Scatter Plot
The ggplot2 syntax begins with ggplot(), specifying the data and aesthetic mappings, then adds geometric objects (geom_*):
ggplot(mtcars, aes(x = wt, y = mpg)) +
geom_point() +
labs(title = "Scatter Plot of Weight vs. MPG",
x = "Weight (1000 lbs)",
y = "Miles per Gallon")
The aes() function maps wt to the x‑axis and mpg to the y‑axis. geom_point() draws the points, and labs() supplies titles and axis labels.
Adding Aesthetic Mappings
Just like in base R, you
can map additional variables to aesthetics like color or shape. So naturally, mPG by Cylinder Count",
x = "Weight (1000 lbs)",
y = "Miles per Gallon",
color = "Cylinders") +
theme_minimal()
Here, `color = factor(cyl)` assigns distinct colors to each cylinder group, and `size` adjusts point size. Here's one way to look at it: to differentiate points by cylinder count:
```r
ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
geom_point(size = 3) +
labs(title = "Weight vs. The `theme_minimal()` function enhances readability with a clean background.
### Adding a Regression Line in ggplot2
To overlay a trend line, use `geom_smooth()` with `method = "lm"`:
```r
ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
geom_point(size = 3) +
geom_smooth(method = "lm", se = FALSE, linetype = "dashed", color = "darkred") +
labs(title = "Weight vs. MPG with Regression Line",
x = "Weight (1000 lbs)",
y = "Miles per Gallon",
color = "Cylinders") +
theme_minimal()
The geom_smooth() layer adds the least-squares fit line, while se = FALSE removes the confidence interval shading. The linetype and color arguments customize the line’s appearance.
Customizing Point Shapes by a Categorical Variable
For non-color mappings, use shape to encode a third variable:
ggplot(mtcars, aes(x = wt, y = mpg, shape = factor(cyl))) +
geom_point(size = 3) +
scale_shape_manual(values = c(16, 17, 18)) + # Assign specific shapes
labs(title = "Weight vs. MPG by Cylinder Shape",
x = "Weight (1000 lbs)",
y = "Miles per Gallon",
shape = "Cylinders") +
theme_minimal()
The scale_shape_manual() function assigns hexadecimal shape codes (e.g., 16 = circle, 17 = square) to cylinder groups. This avoids color-dependent interpretations, useful in black-and-white prints.
Faceting for Subplots
To explore subgroups (e.g., cylinder counts), use facet_wrap():
ggplot(mtcars, aes(x = wt, y = mpg)) +
geom_point() +
geom_smooth(method = "lm", se = FALSE) +
facet_wrap(~ cyl) +
labs(title = "Weight vs. MPG by Cylinder",
x = "Weight (1000 lbs)",
y = "Miles per Gallon") +
theme_minimal()
This splits the plot into panels for 4-, 6-, and 8-cylinder cars, each with its own regression line. Faceting is ideal for comparing distributions across categories.
Final Conclusion
Scatter plots are powerful tools for visualizing relationships between variables. Base R offers straightforward customization via plot(), abline(), and legend(), while ggplot2 provides a more intuitive, layered approach with aes() mappings, geom_ functions, and advanced features like faceting. By mapping variables to aesthetics such as color, shape, or size, you can encode multidimensional data effectively. Whether using base R or ggplot2, always ensure annotations (labels, legends, titles) are clear and contextually relevant. The choice between the two depends on your workflow: base R suits quick analyses, while ggplot2 excels in complex, publication-ready visualizations. When all is said and done, the goal is to communicate insights clearly—whether highlighting trends, outliers, or categorical differences—to inform data-driven decisions Most people skip this — try not to..