R
ggplot
data visualization
x axis
time series

R ggplot display all dates on x axis

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

ggplot2 does not show every date on the x-axis by default because it tries to avoid unreadable labels. If you really want every date displayed, the fix is to control the date scale yourself with explicit breaks and then make the labels readable enough for the amount of data you are plotting.

Use scale_x_date() With Explicit Breaks

The most direct solution is to generate a sequence of dates and pass that sequence to breaks.

r
1library(ggplot2)
2
3df <- data.frame(
4  date = seq(as.Date("2024-01-01"), as.Date("2024-01-07"), by = "day"),
5  value = c(5, 7, 6, 8, 9, 7, 10)
6)
7
8ggplot(df, aes(x = date, y = value)) +
9  geom_line() +
10  geom_point() +
11  scale_x_date(
12    breaks = seq(min(df$date), max(df$date), by = "1 day"),
13    date_labels = "%Y-%m-%d"
14  )

This forces a tick for each day in the dataset. The important part is the seq(..., by = "1 day") call. ggplot2 no longer chooses the breaks for you.

If the data is weekly, monthly, or hourly, change the step accordingly. The underlying idea is the same.

Keep the Labels Readable

Showing all dates is easy. Making the plot readable is the harder part. Once the axis contains many labels, rotate them or shorten the format.

r
1ggplot(df, aes(x = date, y = value)) +
2  geom_col() +
3  scale_x_date(
4    breaks = seq(min(df$date), max(df$date), by = "1 day"),
5    date_labels = "%b %d"
6  ) +
7  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Using %b %d produces labels like Jan 01, which are shorter than full ISO dates. Rotating the text helps prevent overlap when the date range is dense.

If even that becomes unreadable, showing all dates may not be the best visual choice. In those cases, either increase the plot width or choose a less dense break interval.

Make Sure the Column Is Really a Date

A frequent reason axis formatting appears to fail is that the x column is still a character vector instead of class Date. ggplot2 handles date scales only when the data type is correct.

r
str(df$date)

If the column is character, convert it first:

r
df$date <- as.Date(df$date)

For date-time data, use POSIXct and scale_x_datetime() instead of scale_x_date(). Mixing date and date-time types is a common source of confusion when labels or breaks do not behave as expected.

Alternative: Use date_breaks

For evenly spaced date intervals, date_breaks is a convenient shorthand.

r
1ggplot(df, aes(x = date, y = value)) +
2  geom_line() +
3  scale_x_date(
4    date_breaks = "1 day",
5    date_labels = "%d-%b"
6  ) +
7  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))

This is often simpler than building a manual sequence yourself. The tradeoff is that manual breaks = seq(...) gives you more explicit control when the axis limits or data range are irregular.

When Showing Every Date Is the Wrong Goal

Sometimes the chart becomes worse when every date is shown. A plot with 60 daily labels on a narrow figure is technically complete but practically unreadable. In those cases, a better approach is:

  • show fewer breaks such as every 7 days
  • facet the data into shorter ranges
  • increase the plot width in the report or notebook
  • use interactive plotting if exact hover dates matter more than static labels

The best chart is not always the one with the most text on the axis.

Common Pitfalls

A common mistake is trying to force all dates without converting the x column to Date. If the values are still character strings, scale_x_date() will not behave correctly.

Another mistake is using very long date labels on a narrow figure and then assuming ggplot2 is broken because labels overlap. The issue is usually layout, not scale logic.

People also often choose scale_x_date() for date-time data. If the column contains timestamps, scale_x_datetime() is the right scale.

Finally, do not forget that all-date axes are sometimes a readability problem rather than a technical requirement. It is worth asking whether the chart is clearer with fewer labels.

Summary

  • Use scale_x_date() with explicit breaks or date_breaks to show every date.
  • Keep the x column as class Date, not plain character.
  • Rotate or shorten labels when the axis becomes crowded.
  • Use scale_x_datetime() for timestamp data instead of pure dates.
  • Showing every date is possible, but readability should still guide the final plot design.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.