ggplot2 geom_line() in R: Line Charts With Examples
The geom_line() function in ggplot2 connects points in order of x to draw a line. Use it for time series, trends, and any continuous relationship where reading x as a sequence makes sense.
ggplot(df, aes(x, y)) + geom_line() # basic line ggplot(df, aes(x, y, color = group)) + geom_line() # one line per group ggplot(df, aes(x, y, group = group)) + geom_line() # multi-line, no color ggplot(df, aes(x, y, linetype = group)) + geom_line() # different linetypes ggplot(df, aes(x, y)) + geom_line(linewidth = 1.2) # thicker line ggplot(df, aes(x, y)) + geom_line() + geom_point() # line + markers ggplot(df, aes(x, y)) + geom_line() + scale_x_date() # time series
Need explanation? Read on for examples and pitfalls.
What geom_line() does in one sentence
geom_line() draws a line connecting points in ascending order of x. Each row contributes one point; ggplot connects them with straight segments. Use the group aesthetic to draw multiple lines, one per group, in the same plot.
Unlike geom_path() (which connects points in row order regardless of x), geom_line() always sorts by x first. This makes it the right choice for time series and any plot where x represents a continuous independent variable.
Syntax
geom_line() is a layer added to a ggplot() call. Minimum is aes(x, y). For multi-line plots, also map group, color, or linetype.
The full signature:
geom_line(mapping = NULL, data = NULL, stat = "identity", position = "identity",
..., na.rm = FALSE, orientation = NA, show.legend = NA, inherit.aes = TRUE)
linewidth (ggplot2 3.4+), not size, for line thickness. geom_line(linewidth = 1.2) is the modern parameter. The old size = 1.2 still works but produces deprecation warnings in newer ggplot2 versions.Six common patterns
1. Basic time series line
The simplest case: x is a date, y is a numeric, line connects them in chronological order.
2. Multi-line with color
color = sex automatically groups the data; ggplot draws one line per unique sex value.
3. Different linetypes per group
linetype maps to one of "solid", "dashed", "dotted", "dotdash", etc. Useful when colors are not appropriate (e.g., grayscale printing).
4. Line + points
A common combo: the line shows the trend, points emphasize each measurement. Useful when data is sparse and individual values matter.
5. Group without color
Use group = sex (in aes) when you need separate lines but do NOT want the legend / color to encode it. Useful when one variable is the focus and other groupings are reference.
6. Stepped line for discrete jumps
geom_step() connects with right-angle steps, not slanted lines. Right for state changes (e.g., Markov chains, on/off signals) where interpolation between values does not make sense.
geom_line() requires that ggplot can identify which points belong to the same line. With one line, just aes(x, y) is enough. With multiple lines, you MUST map color, linetype, or group to a grouping variable. Without that, ggplot zigzags trying to connect every point in x order, producing a tangled mess.geom_line() vs base R plot(type = "l")
Base R uses plot(type = "l") or lines(). ggplot2 makes line plots composable and grouping explicit.
| Task | ggplot2 | Base R |
|---|---|---|
| Single line | geom_line() |
plot(x, y, type = "l") |
| Multiple lines | aes(group/color = grp) |
(loop with lines() per group) |
| Line + points | + geom_line() + geom_point() |
plot(type = "b") or o |
| Line types | aes(linetype = grp) |
lty = ... per call |
| Time-series x | + scale_x_date() |
plot.Date() |
| Add legend | automatic from aes | legend(...) manually |
When to use which:
- Use ggplot2 for multi-group, faceted, or publication line plots.
- Use base
plot(type = "l")for one-line interactive exploration.
Common pitfalls
Pitfall 1: missing group aesthetic for multi-line. Without group, color, or linetype mapped to a categorical variable, ggplot tries to connect ALL points in x order, producing a single zigzag line across all groups. Symptom: looks like a sawtooth wave.
Pitfall 2: confusing geom_line() with geom_path(). geom_line sorts by x first; geom_path connects in ROW order. For time series, geom_line; for paths through space (e.g., GPS tracks), geom_path.
size is deprecated for line thickness in ggplot2 3.4+; use linewidth. Old code with geom_line(size = 1.5) still works but warns. Update to geom_line(linewidth = 1.5) for new work.Pitfall 3: factor x axis with continuous group. aes(x = factor(year), y = val, group = 1) is needed when x is a factor but you still want a continuous line. Without group = 1, ggplot draws no line.
Try it yourself
Try it: Plot economics showing unemploy over date as a line, but ALSO map unemploy to color so the line color shifts with the value. Save to ex_plot.
Click to reveal solution
Explanation: Mapping color = unemploy makes the line color encode the y value. scale_color_gradient() defines the low-to-high color ramp. Higher unemployment = redder line.
Related ggplot2 functions
After mastering geom_line(), look at:
geom_path(): connect in row order (not x order)geom_step(): right-angle steps for discrete state changesgeom_area(): filled area under a linegeom_ribbon(): band between two y values (e.g., confidence intervals)geom_smooth(): fit a smooth trend line through pointsscale_x_date(),scale_x_datetime(): date and datetime axis formatting
For animated transitions over time, gganimate::transition_reveal() builds an animated geom_line.
FAQ
How do I add multiple lines to a ggplot?
Map a categorical variable to color, linetype, or group: aes(x, y, color = group). ggplot draws one line per unique group value. If you do not want color in the legend, use group = group instead.
What is the difference between geom_line and geom_path in ggplot2?
geom_line() connects points in ASCENDING x ORDER. geom_path() connects in ROW ORDER (no sorting). For time series, use geom_line. For trajectories or paths through space, use geom_path.
How do I change the line color in geom_line?
For ALL lines: geom_line(color = "blue") (outside aes). To map color to a variable: aes(color = group) (inside aes). Don't mix them up; the wrong form is the most common ggplot2 error.
How do I make a thicker line in ggplot2?
Use linewidth: geom_line(linewidth = 1.5). The old size argument is deprecated in ggplot2 3.4+. Default linewidth is 0.5; values 1 to 2 are typical for clearer plots.
How do I plot a time series in ggplot2?
Use geom_line() with x as a Date or POSIXct column: ggplot(df, aes(x = date, y = value)) + geom_line(). Use scale_x_date() for date-formatted axis labels: + scale_x_date(date_breaks = "1 year", date_labels = "%Y").