<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/customizing-time-and-date-scales-in-ggplot2/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://www.statworx.com/de/blog/customizing-time-and-date-scales-in-ggplot2/"> r-bloggers – STATWORX</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>In the <a rel="nofollow" href="https://www.statworx.com/blog/coordinate-systems-in-ggplot2-easily-overlooked-and-rather-underrated/" target="_blank">last post</a> of this series we dealt with axis systems. In this post we are also dealing with axes but this time we are taking a look at the position scales of dates, time and datetimes. Since we at <a rel="nofollow" href="https://www.statworx.com/de/" target="_blank">STATWORX</a> are often forecasting – and thus plotting – time series, this is an important issue for us. The choice of axis ticks and labels can make the message conveyed by a plot clearer. Oftentimes, some points in time are – e.g. due to their business implications – more important than others and should be easily identified. Unequivocal, yet parsimonious labeling is key to the readability of any plot. Luckily, ggplot2 enables us to do so for dates and times with almost any effort at all. </p>
<p>We are using ggplot`s economics data set. Our base Plot looks like this:</p>
<p><img alt="ggplot-base-plot" src="https://i1.wp.com/www.statworx.com/wp-content/uploads/ggplot-base-plot.jpg?w=450&ssl=1" class="wp-image-14319" data-recalc-dims="1"></p>
<pre><code lang="python"># base plot
base_plot &lt;- ggplot(data = economics) +
  geom_line(aes(x = date, y = unemploy), 
            color = &quot;#09557f&quot;,
            alpha = 0.6,
            size = 0.6) +
  labs(x = &quot;Date&quot;, 
       y = &quot;US Unemployed in Thousands&quot;,
       title = &quot;Base Plot&quot;) +
  theme_minimal()
</code></pre>
<h2>Scale Types</h2>
<p>As of now, <code>ggplot2</code> supports three date and time classes: <code>POSIXct</code>, <code>Date</code> and <code>hms</code>.<br>
Depending on the class at hand, axis ticks and labels can be controlled by using <code>scale_*_date</code>, <code>scale_*_datetime</code> or <code>scale_*_time</code>, respectively. Depending on whether one wants to modify the x or the y axis <code>scale_x_*</code> or <code>scale_y_*</code> are to be employed. For sake of simplicity, in the examples only <code>scale_x_date</code> is employed, but all discussed arguments work just the same for all mentioned scales. </p>
<h2>Minor Modifications</h2>
<p>Let’s start easy. With the argument <code>limits</code> the range of the displayed dates or time can be set. Two values of the correct date or time class have to be supplied. </p>
<p><img alt="ggplot-limits-set" src="https://i1.wp.com/www.statworx.com/wp-content/uploads/ggplot-limits-set.jpg?w=450&ssl=1" class="wp-image-14346" data-recalc-dims="1"></p>
<pre><code> base_plot +
   scale_x_date(limits = as.Date(c(&quot;1980-01-01&quot;,&quot;2000-01-01&quot;))) +
   ggtitle(&quot;limits = as.Date(c(\&quot;1980-01-01\&quot;,\&quot;2000-01-01\&quot;))&quot;)
</code></pre>
<p>The <code>expand</code> argument ensures that there is some distance between the displayed data and the axes. The argument <code>expand</code> takes two numeric values, the first is the multiplicative expansion constant, the second the additive expansion constant. The larger one of the two distances is employed in the plot, the multiplicative constant is multiplied with the range of the displayed data, the additive is multiplied with one unit of the depicted data. The resulting empty space is added at the left and right end of the x-axis or the top and bottom of the y-axis. </p>
<p><img alt="ggplot-expand-set" src="https://i0.wp.com/www.statworx.com/wp-content/uploads/ggplot-expand-set.jpg?w=450&ssl=1" class="wp-image-14337" data-recalc-dims="1"></p>
<pre><code> base_plot +  
 scale_x_date(expand = c(0, 5000)) +   #5000/365 = 13.69863 years
   ggtitle(&quot;expand = c(0, 5000)&quot;)
</code></pre>
<p><code>position</code> argument defines where the labels are displayed: Either <code>“left”</code> or <code>“right”</code> from the y-axis or on the <code>“top”</code> or on the <code>“bottom”</code> of the x-axis.</p>
<p><img alt="ggplot-position-set" src="https://i0.wp.com/www.statworx.com/wp-content/uploads/ggplot-position-set.jpg?w=450&ssl=1" class="wp-image-14349" data-recalc-dims="1"></p>
<pre><code> base_plot +  
   scale_x_date(position = &quot;top&quot;) +
   ggtitle(&quot;position = \&quot;top\&quot;&quot;)
</code></pre>
<h2>Axis Ticks and Grid Lines</h2>
<p>More essential than the cosmetic modifications discussed so far are the axis ticks. There are several ways to define the axis ticks of dates and times. There are the labelled <em>major breaks</em> and further the <em>minor breaks</em>, which are not labeled but marked by grid lines. These can be customized with the arguments <code>breaks</code> and <code>minor_breaks</code>, respectively. The <code>breaks</code> as the well as <code>minor_breaks</code> can be defined by a numeric vector of exact positions or a function with the axis limits as inputs and breaks as outputs. Alternatively, the arguments can be set to <code>NULL</code> to display (minor) breaks at all. These options are especially handy if irregular intervals between breaks are desired. </p>
<p><img alt="ggplot-breaks-fixed-dates" src="https://i1.wp.com/www.statworx.com/wp-content/uploads/ggplot-breaks-fixed-dates.jpg?w=450&ssl=1" class="wp-image-14325" data-recalc-dims="1"></p>
<pre><code> base_plot +  
  scale_x_date(breaks = as.Date(c(&quot;1970-01-01&quot;, &quot;2000-01-01&quot;)),
               minor_breaks = as.Date(c(&quot;1975-01-01&quot;, &quot;1980-01-01&quot;,
                                        &quot;2005-01-01&quot;, &quot;2010-01-01&quot;))) +
   ggtitle(&quot;(minor_)breaks = fixed Dates&quot;)
</code></pre>
<p><img alt="ggplot-breaks-custom-function" src="https://i0.wp.com/www.statworx.com/wp-content/uploads/ggplot-breaks-custom-function.jpg?w=450&ssl=1" class="wp-image-14322" data-recalc-dims="1"></p>
<pre><code> base_plot +  
   scale_x_date(breaks = function(x) seq.Date(from = min(x), 
   											  to = max(x), 
   											  by = &quot;12 years&quot;),
                minor_breaks = function(x) seq.Date(from = min(x), 
                									to = max(x), 
                									by = &quot;2 years&quot;)) +
   ggtitle(&quot;(minor_)breaks = custom function&quot;)
</code></pre>
<p><img alt="ggplot-breaks-NULL" src="https://i2.wp.com/www.statworx.com/wp-content/uploads/ggplot-breaks-NULL.jpg?w=450&ssl=1" class="wp-image-14328" data-recalc-dims="1"></p>
<pre><code> base_plot +  
  scale_x_date(breaks = NULL,
               minor_breaks = NULL) +
   ggtitle(&quot;(minor_)breaks = NULL&quot;)
</code></pre>
<p>Another and very convenient way to define regular breaks are the <code>date_breaks</code> and the <code>date_minor_breaks</code> argument. As input both arguments take a character vector combining a string specifying the time unit (either “sec&quot;, &quot;min&quot;, &quot;hour&quot;, &quot;day&quot;, &quot;week&quot;, &quot;month&quot; or &quot;year&quot;) and an integer specifying number of said units specifying the break intervals.</p>
<p><img alt="ggplot-date-breaks-set" src="https://i1.wp.com/www.statworx.com/wp-content/uploads/ggplot-date-breaks-set.jpg?w=450&ssl=1" class="wp-image-14331" data-recalc-dims="1"></p>
<pre><code>base_plot +
  scale_x_date(date_breaks = &quot;10 years&quot;,
               date_minor_breaks = &quot;2 years&quot;) +
  ggtitle(&quot;date_(minor_)breaks = \&quot;x years\&quot;&quot;)
</code></pre>
<p>If both are given, <code>date(_minor)_breaks</code> overrules <code>(minor_)breaks</code>.</p>
<h2>Axis Labels</h2>
<p>Similar to the axis ticks, the format of the displayed labels can either be defined via the <code>labels</code> or the <code>date_labels</code> argument. The <code>labels</code> argument can either be set to <code>NULL</code> if no labels should be displayed, with the breaks as inputs and the labels as outputs. Alternatively, a character vector with labels for all the breaks can be supplied to the argument. This can be very useful, since like this virtually any character vector can be used to label the breaks. The number of labels must be the same as the number of breaks. If the breaks are defined by a function, <code>date_breaks</code> or by default the labels must be defined by a function as well. </p>
<p><img alt="ggplot-lables-function" src="https://i1.wp.com/www.statworx.com/wp-content/uploads/ggplot-lables-function.jpg?w=450&ssl=1" class="wp-image-14340" data-recalc-dims="1"></p>
<pre><code>base_plot +
  scale_x_date(date_breaks = &quot;15 years&quot;,
               labels = function(x) paste((x-365), &quot;(+365 days)&quot;)) +
  ggtitle(&quot;labels = custom function&quot;) 
</code></pre>
<p><img alt="ggplot-lables-vector" src="https://i2.wp.com/www.statworx.com/wp-content/uploads/ggplot-lables-vector.jpg?w=450&ssl=1" class="wp-image-14343" data-recalc-dims="1"></p>
<pre><code>base_plot +
  scale_x_date(breaks = as.Date(c(&quot;1970-01-01&quot;, &quot;2000-01-01&quot;)),
               labels = c(&quot;~ '70&quot;, &quot;~ '00&quot;)) +
  ggtitle(&quot;labels = character vector&quot;)   
</code></pre>
<p>Furthermore and very conveniently, the format of the labels can be controlled via the argument <code>date_labels</code> set to a string of formatting codes, defining order, format and elements to be displayed:</p>
<figure>
<table>
<thead>
<tr>
<th>Code</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td>%S</td>
<td>second (00-59)</td>
</tr>
<tr>
<td>%M</td>
<td>minute (00-59)</td>
</tr>
<tr>
<td>%l</td>
<td>hour, in 12-hour clock (1-12)</td>
</tr>
<tr>
<td>%I</td>
<td>hour, in 12-hour clock (01-12)</td>
</tr>
<tr>
<td>%H</td>
<td>hour, in 24-hour clock (01-24)</td>
</tr>
<tr>
<td>%a</td>
<td>day of the week, abbreviated (Mon-Sun)</td>
</tr>
<tr>
<td>%A</td>
<td>day of the week, full (Monday-Sunday)</td>
</tr>
<tr>
<td>%e</td>
<td>day of the month (1-31)</td>
</tr>
<tr>
<td>%d</td>
<td>day of the month (01-31)</td>
</tr>
<tr>
<td>%m</td>
<td>month, numeric (01-12)</td>
</tr>
<tr>
<td>%b</td>
<td>month, abbreviated (Jan-Dec)</td>
</tr>
<tr>
<td>%B</td>
<td>month, full (January-December)</td>
</tr>
<tr>
<td>%y</td>
<td>year, without century (00-99)</td>
</tr>
<tr>
<td>%Y</td>
<td>year, with century (0000-9999)</td>
</tr>
</tbody>
</table>
</figure>
<p>Source: Wickham 2009 p. 99</p>
<p><img alt="ggplot-date-lables-set" src="https://i1.wp.com/www.statworx.com/wp-content/uploads/ggplot-date-lables-set.jpg?w=450&ssl=1" class="wp-image-14334" data-recalc-dims="1"></p>
<pre><code>base_plot +
  scale_x_date(date_labels = &quot;%Y (%b)&quot;) +
  ggtitle(&quot;date_labels = \&quot;%Y (%b)\&quot;&quot;) 
</code></pre>
<p>The choice of axis ticks and labels might seem trivial. However, one should not underestimate the amount of confusion that can be caused by too many, too less or poorly positioned axis ticks and labels. Further, economical yet clear labeling of axis ticks can increase the readability and visual appeal of any time series plot immensely. Since it is so easy to tweak the date and time axes in ggplot2 there is simply no excuse not to do so. </p>
<h2>References</h2>
<ul>
<li>Wickham, H. (2009). <em>ggplot2: elegant graphics for data analysis</em>. Springer.</li>
</ul>
<div>
<h6>Über den Autor</h6>
<p><img src="https://i0.wp.com/www.statworx.com/wp-content/uploads/statworx-avatar-female-300x300.png?resize=180%2C180&ssl=1" width="180" alt="Lea Waniek" class="wp-user-avatar wp-user-avatar-180" data-recalc-dims="1" height="180"></p>
<div>
<h4>Lea Waniek</h4>
<p>Lea ist Mitglied im Data Science Team und unterstützt ebenfalls im Bereich Statistik.</p>
</div>
</div>
<p>Der Beitrag <a rel="nofollow" href="https://www.statworx.com/de/blog/customizing-time-and-date-scales-in-ggplot2/" target="_blank">Customizing time and date scales in ggplot2</a> erschien zuerst auf <a rel="nofollow" href="https://www.statworx.com/de" target="_blank">STATWORX</a>.</p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://www.statworx.com/de/blog/customizing-time-and-date-scales-in-ggplot2/"> r-bloggers – STATWORX</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/54IXNIMROQI" height="1"></a></div>