ggplot2::geom_line()
geom_line(mapping = NULL, data = NULL, stat = "identity", position = "identity", ...) geom_line() connects data points in the order they appear in the data with a line. It’s the standard choice for time series, sequential measurements, and anywhere the x-axis represents time or a meaningful sequence rather than independent categories.
Syntax
geom_line(mapping = NULL, data = NULL, stat = "identity", position = "identity", ...)
| Argument | What it does |
|---|---|
mapping | Aesthetic mappings from aes() |
data | Data frame for this layer |
stat | Almost always "identity" — leave data as-is |
position | Usually "identity" |
na.rm | Remove missing values silently |
orientation | "x" (default), "y", or NA (auto-detect) |
Basic Usage
library(ggplot2)
# Simple line plot
ggplot(economics, aes(x = date, y = psavert)) +
geom_line()
The x-axis is the date and the y-axis is personal savings rate. The line shows the trend over time. economics is a built-in ggplot2 dataset with US economic time series data.
Why Order Matters
geom_line() connects points in the order they appear in the data. This is different from geom_path(), which connects them in the order they appear on the screen. If your data is not sorted by the x-axis variable, the line will zigzag incorrectly:
# Sort first — otherwise the line jumps all over the place
ggplot(economics, aes(x = date, y = psavert)) +
geom_line() +
geom_point() # shows the actual data positions
Always sort your data by the x-axis variable before plotting lines if the data comes from an unsorted source.
Mapping Colour to a Group
For multiple lines (e.g., different categories over time), map colour to the grouping variable:
# Multiple time series coloured by category
ggplot(peaks, aes(x = year, y = elevation, colour = peak)) +
geom_line()
This draws one line per unique colour value, all on the same axes. ggplot2 automatically splits and colours the lines.
Line Aesthetic Options
Control the appearance with standard aesthetics:
ggplot(economics, aes(x = date, y = psavert)) +
geom_line(
colour = "steelblue",
linewidth = 0.8,
linetype = "solid"
)
linewidth(or deprecatedsize) controls thickness in mmlinetypeaccepts:"solid","dashed","dotted","dotdash","longdash","twodash"colouraccepts colour names, hex codes, or mapped variables
Combining with Points
Often you want both — line for the trend, points for the individual observations:
ggplot(economics, aes(x = date, y = psavert)) +
geom_line() +
geom_point(size = 0.8, alpha = 0.5)
Small points with some transparency let you see both the line and the raw data without clutter.
Multiple Series with Facets
When you have multiple series that shouldn’t share a y-axis, facet_wrap() is cleaner than overlaying many coloured lines:
ggplot(gafa_stock, aes(x = Date, y = Close)) +
geom_line() +
facet_wrap(~ Symbol, scales = "free_y")
Each stock gets its own panel with its own y-axis scale.
Handling Missing Data
geom_line() has na.rm = FALSE by default — it breaks the line at missing values rather than interpolating. This is usually what you want for time series, but be aware:
# Line breaks at NA values
df <- data.frame(
x = 1:5,
y = c(1, 2, NA, 4, 5)
)
ggplot(df, aes(x, y)) + geom_line()
# Line goes 1 -> 2, breaks, resumes 4 -> 5
Use geom_line(na.rm = TRUE) to silently skip missing values and connect across them.
Orientation
When the x-axis is categorical or the data orientation is ambiguous, set orientation:
# Horizontal line plot
ggplot(mtcars, aes(y = mpg)) +
geom_line(group = 1) # one line across all cars
Or orientation = "y" to treat the y variable as the grouping axis.
Line vs Path
geom_line() connects points in data order. geom_path() connects them in the order they appear on the plot (as if you drew the line on screen):
# geom_line: x-axis order determines connection
ggplot(df, aes(x = x, y = y)) + geom_line()
# geom_path: follows the actual path drawn on screen
# Useful for directional data, GPS tracks, etc.
ggplot(gps_data, aes(x = lon, y = lat)) + geom_path()
For time series, geom_line() is almost always what you want.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mapping | aesthetic | NULL | Aesthetic mappings |
data | data.frame | NULL | Layer data |
stat | string | "identity" | Leave as-is |
position | string/position | "identity" | Position adjustment |
na.rm | logical | FALSE | Skip missing values silently |
orientation | string | NA | "x", "y", or NA for auto |
show.legend | logical/NA | NA | Show in legend |
inherit.aes | logical | TRUE | Inherit global aesthetics |
See Also
- /reference/tidyverse/ggplot2_geom_point/ — scatter plots, the complement to line charts
- /tutorials/r-data-visualization/introduction-to-ggplot2/ — layered grammar concept behind both geoms
- /reference/tidyverse/ggplot2_aes/ — aesthetic mapping system both geoms share