Calendar Heatmap

[This article was first published on Data Science 42, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Visualise time series data in calendar style –

Nowadays you can find calendar heatmaps on every GitHub profile. The first time I saw a one, it was the winning entry for the JSM Data Expo in 2009. What amazed me most was that it was created in SAS which is not especially well-known for nice visualisations. Only a short time later the R community was able to replicate similar calendar heatmaps thanks to Paul Bleicher’s lattice based implementation.

Being always a big fan of Hadley Wickham’s ggplot2 I wanted to implement my own calendar heatmap version in ggplot2. For plotting your own time-series you only need the ggplot2 package and the following function. The lubridate package might come in handy to transform the dates. One nice feature of my solution is that you can adjust the ggplot object as you like.

Preview

Code

<span class="cd">#' Calendar Heatmap</span><span class="w">
</span><span class="cd">#' </span><span class="w">
</span><span class="cd">#' Creates a colour coded calendar visualising time series data</span><span class="w">
</span><span class="cd">#' </span><span class="w">
</span><span class="cd">#' @param dates A vector containing the dates in `Date` format.</span><span class="w">
</span><span class="cd">#' @param values A vector containing the corresponding values as numeric.</span><span class="w">
</span><span class="cd">#' @param title Main plot title (optional).</span><span class="w">
</span><span class="cd">#' @param subtitle Main plot subtitle (optional).</span><span class="w">
</span><span class="cd">#' @param legendtitle Legend title (optional).</span><span class="w">
</span><span class="cd">#'   </span><span class="w">
</span><span class="cd">#' @return ggplot object</span><span class="w">
</span><span class="n">calendarHeatmap</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="k">function</span><span class="p">(</span><span class="n">dates</span><span class="p">,</span><span class="w"> </span><span class="n">values</span><span class="p">,</span><span class="w"> </span><span class="n">title</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w"> </span><span class="n">subtitle</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w"> </span><span class="n">legendtitle</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">){</span><span class="w">
  
  </span><span class="c1"># Parameter checks</span><span class="w">
  </span><span class="k">if</span><span class="p">(</span><span class="nf">missing</span><span class="p">(</span><span class="n">dates</span><span class="p">)){</span><span class="w">
    </span><span class="n">stop</span><span class="p">(</span><span class="s2">"Need to specify a dates vector."</span><span class="p">)</span><span class="w">
  </span><span class="p">}</span><span class="w">
  </span><span class="k">if</span><span class="p">(</span><span class="nf">missing</span><span class="p">(</span><span class="n">values</span><span class="p">)){</span><span class="w">
    </span><span class="n">stop</span><span class="p">(</span><span class="s2">"Need to specify a values vector."</span><span class="p">)</span><span class="w">
  </span><span class="p">}</span><span class="w">
  </span><span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">is.Date</span><span class="p">(</span><span class="n">dates</span><span class="p">)){</span><span class="w">
    </span><span class="n">stop</span><span class="p">(</span><span class="s2">"dates vector need to be in Date format."</span><span class="p">)</span><span class="w">
  </span><span class="p">}</span><span class="w">
  </span><span class="k">if</span><span class="p">(</span><span class="nf">length</span><span class="p">(</span><span class="n">dates</span><span class="p">)</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nf">length</span><span class="p">(</span><span class="n">values</span><span class="p">)){</span><span class="w">
    </span><span class="n">stop</span><span class="p">(</span><span class="s2">"dates and values need to have the same length."</span><span class="p">)</span><span class="w">
  </span><span class="p">}</span><span class="w">
    
  
  </span><span class="c1"># load required packages</span><span class="w">
  </span><span class="n">require</span><span class="p">(</span><span class="n">ggplot2</span><span class="p">)</span><span class="w">
  
  </span><span class="n">my_theme</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="k">function</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
    
    </span><span class="c1"># Colors</span><span class="w">
    </span><span class="n">color.background</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"white"</span><span class="w">
    </span><span class="n">color.text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"#22211d"</span><span class="w">
    
    </span><span class="c1"># Begin construction of chart</span><span class="w">
    </span><span class="n">theme_bw</span><span class="p">(</span><span class="n">base_size</span><span class="o">=</span><span class="m">15</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w">
      
      </span><span class="c1"># Format background colors</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">panel.background</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">element_rect</span><span class="p">(</span><span class="n">fill</span><span class="o">=</span><span class="n">color.background</span><span class="p">,</span><span class="w"> </span><span class="n">color</span><span class="o">=</span><span class="n">color.background</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">plot.background</span><span class="w">  </span><span class="o">=</span><span class="w"> </span><span class="n">element_rect</span><span class="p">(</span><span class="n">fill</span><span class="o">=</span><span class="n">color.background</span><span class="p">,</span><span class="w"> </span><span class="n">color</span><span class="o">=</span><span class="n">color.background</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">panel.border</span><span class="w">     </span><span class="o">=</span><span class="w"> </span><span class="n">element_rect</span><span class="p">(</span><span class="n">color</span><span class="o">=</span><span class="n">color.background</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">strip.background</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">element_rect</span><span class="p">(</span><span class="n">fill</span><span class="o">=</span><span class="n">color.background</span><span class="p">,</span><span class="w"> </span><span class="n">color</span><span class="o">=</span><span class="n">color.background</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w">
      
      </span><span class="c1"># Format the grid</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">panel.grid.major</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">element_blank</span><span class="p">())</span><span class="w"> </span><span class="o">+</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">panel.grid.minor</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">element_blank</span><span class="p">())</span><span class="w"> </span><span class="o">+</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">axis.ticks</span><span class="w">       </span><span class="o">=</span><span class="w"> </span><span class="n">element_blank</span><span class="p">())</span><span class="w"> </span><span class="o">+</span><span class="w">
      
      </span><span class="c1"># Format the legend</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">legend.position</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"bottom"</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">legend.text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">element_text</span><span class="p">(</span><span class="n">size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">8</span><span class="p">,</span><span class="w"> </span><span class="n">color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">color.text</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">legend.title</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">element_text</span><span class="p">(</span><span class="n">size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">10</span><span class="p">,</span><span class="w"> </span><span class="n">face</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"bold"</span><span class="p">,</span><span class="w"> </span><span class="n">color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">color.text</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w">
      
      </span><span class="c1"># Format title and axis labels</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">plot.title</span><span class="w">       </span><span class="o">=</span><span class="w"> </span><span class="n">element_text</span><span class="p">(</span><span class="n">color</span><span class="o">=</span><span class="n">color.text</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="o">=</span><span class="m">20</span><span class="p">,</span><span class="w"> </span><span class="n">face</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"bold"</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">axis.text.x</span><span class="w">      </span><span class="o">=</span><span class="w"> </span><span class="n">element_text</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="m">12</span><span class="p">,</span><span class="w"> </span><span class="n">color</span><span class="o">=</span><span class="s2">"black"</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">axis.text.y</span><span class="w">      </span><span class="o">=</span><span class="w"> </span><span class="n">element_text</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="m">12</span><span class="p">,</span><span class="w"> </span><span class="n">color</span><span class="o">=</span><span class="s2">"black"</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">axis.title.x</span><span class="w">     </span><span class="o">=</span><span class="w"> </span><span class="n">element_text</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="m">14</span><span class="p">,</span><span class="w"> </span><span class="n">color</span><span class="o">=</span><span class="s2">"black"</span><span class="p">,</span><span class="w"> </span><span class="n">face</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"bold"</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">axis.title.y</span><span class="w">     </span><span class="o">=</span><span class="w"> </span><span class="n">element_text</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="m">14</span><span class="p">,</span><span class="w"> </span><span class="n">color</span><span class="o">=</span><span class="s2">"black"</span><span class="p">,</span><span class="w"> </span><span class="n">vjust</span><span class="o">=</span><span class="m">1.25</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">axis.text.x</span><span class="w">      </span><span class="o">=</span><span class="w"> </span><span class="n">element_text</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="m">10</span><span class="p">,</span><span class="w"> </span><span class="n">hjust</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">0</span><span class="p">,</span><span class="w"> </span><span class="n">color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">color.text</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">axis.text.y</span><span class="w">      </span><span class="o">=</span><span class="w"> </span><span class="n">element_text</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="m">10</span><span class="p">,</span><span class="w"> </span><span class="n">color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">color.text</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">strip.text</span><span class="w">       </span><span class="o">=</span><span class="w"> </span><span class="n">element_text</span><span class="p">(</span><span class="n">face</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"bold"</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w"> 
      
      </span><span class="c1"># Plot margins</span><span class="w">
      </span><span class="n">theme</span><span class="p">(</span><span class="n">plot.margin</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">unit</span><span class="p">(</span><span class="nf">c</span><span class="p">(</span><span class="m">0.35</span><span class="p">,</span><span class="w"> </span><span class="m">0.2</span><span class="p">,</span><span class="w"> </span><span class="m">0.3</span><span class="p">,</span><span class="w"> </span><span class="m">0.35</span><span class="p">),</span><span class="w"> </span><span class="s2">"cm"</span><span class="p">))</span><span class="w">
  </span><span class="p">}</span><span class="w">
  
  </span><span class="c1"># create empty calendar</span><span class="w">
  </span><span class="n">min.date</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">as.Date</span><span class="p">(</span><span class="n">paste</span><span class="p">(</span><span class="n">format</span><span class="p">(</span><span class="nf">min</span><span class="p">(</span><span class="n">dates</span><span class="p">),</span><span class="w"> </span><span class="s2">"%Y"</span><span class="p">),</span><span class="s2">"-1-1"</span><span class="p">,</span><span class="n">sep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">))</span><span class="w">
  </span><span class="n">max.date</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">as.Date</span><span class="p">(</span><span class="n">paste</span><span class="p">(</span><span class="n">format</span><span class="p">(</span><span class="nf">max</span><span class="p">(</span><span class="n">dates</span><span class="p">),</span><span class="w"> </span><span class="s2">"%Y"</span><span class="p">),</span><span class="s2">"-12-31"</span><span class="p">,</span><span class="w"> </span><span class="n">sep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">))</span><span class="w">
  </span><span class="n">df</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">data.frame</span><span class="p">(</span><span class="n">date</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">seq</span><span class="p">(</span><span class="n">min.date</span><span class="p">,</span><span class="w"> </span><span class="n">max.date</span><span class="p">,</span><span class="w"> </span><span class="n">by</span><span class="o">=</span><span class="s2">"days"</span><span class="p">),</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">NA</span><span class="p">)</span><span class="w">
  
  </span><span class="c1"># fill in values</span><span class="w">
  </span><span class="n">df</span><span class="o">$</span><span class="n">value</span><span class="p">[</span><span class="n">match</span><span class="p">(</span><span class="n">dates</span><span class="p">,</span><span class="w"> </span><span class="n">df</span><span class="o">$</span><span class="n">date</span><span class="p">)]</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">values</span><span class="w">
  
  </span><span class="n">df</span><span class="o">$</span><span class="n">year</span><span class="w">  </span><span class="o"><-</span><span class="w">  </span><span class="n">as.factor</span><span class="p">(</span><span class="n">format</span><span class="p">(</span><span class="n">df</span><span class="o">$</span><span class="n">date</span><span class="p">,</span><span class="w"> </span><span class="s2">"%Y"</span><span class="p">))</span><span class="w">
  </span><span class="n">df</span><span class="o">$</span><span class="n">month</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="nf">as.numeric</span><span class="p">(</span><span class="n">format</span><span class="p">(</span><span class="n">df</span><span class="o">$</span><span class="n">date</span><span class="p">,</span><span class="w"> </span><span class="s2">"%m"</span><span class="p">))</span><span class="w">
  </span><span class="n">df</span><span class="o">$</span><span class="n">doy</span><span class="w">   </span><span class="o"><-</span><span class="w"> </span><span class="nf">as.numeric</span><span class="p">(</span><span class="n">format</span><span class="p">(</span><span class="n">df</span><span class="o">$</span><span class="n">date</span><span class="p">,</span><span class="w"> </span><span class="s2">"%j"</span><span class="p">))</span><span class="w">
  </span><span class="c1">#df$dow  <- as.numeric(format(df$date, "%u"))</span><span class="w">
  </span><span class="c1">#df$woy  <- as.numeric(format(df$date, "%W"))</span><span class="w">
  </span><span class="n">df</span><span class="o">$</span><span class="n">dow</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="nf">as.numeric</span><span class="p">(</span><span class="n">format</span><span class="p">(</span><span class="n">df</span><span class="o">$</span><span class="n">date</span><span class="p">,</span><span class="w"> </span><span class="s2">"%w"</span><span class="p">))</span><span class="w">
  </span><span class="n">df</span><span class="o">$</span><span class="n">woy</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="nf">as.numeric</span><span class="p">(</span><span class="n">format</span><span class="p">(</span><span class="n">df</span><span class="o">$</span><span class="n">date</span><span class="p">,</span><span class="w"> </span><span class="s2">"%U"</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="m">1</span><span class="w">
  
  </span><span class="n">df</span><span class="o">$</span><span class="n">dowmapped</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">ordered</span><span class="p">(</span><span class="n">df</span><span class="o">$</span><span class="n">dow</span><span class="p">,</span><span class="w"> </span><span class="n">levels</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">6</span><span class="o">:</span><span class="m">0</span><span class="p">)</span><span class="w">
  </span><span class="n">levels</span><span class="p">(</span><span class="n">df</span><span class="o">$</span><span class="n">dowmapped</span><span class="p">)</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">rev</span><span class="p">(</span><span class="nf">c</span><span class="p">(</span><span class="s2">"Sunday"</span><span class="p">,</span><span class="s2">"Monday"</span><span class="p">,</span><span class="s2">"Tuesday"</span><span class="p">,</span><span class="s2">"Wednesday"</span><span class="p">,</span><span class="s2">"Thursday"</span><span class="p">,</span><span class="s2">"Friday"</span><span class="p">,</span><span class="s2">"Saturday"</span><span class="p">))</span><span class="w">
  
  </span><span class="n">g</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">ggplot</span><span class="p">(</span><span class="n">df</span><span class="p">,</span><span class="w"> </span><span class="n">aes</span><span class="p">(</span><span class="n">woy</span><span class="p">,</span><span class="w"> </span><span class="n">dowmapped</span><span class="p">,</span><span class="w"> </span><span class="n">fill</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">value</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w"> 
    </span><span class="n">geom_tile</span><span class="p">(</span><span class="n">colour</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"darkgrey"</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> 
    </span><span class="n">facet_wrap</span><span class="p">(</span><span class="o">~</span><span class="n">year</span><span class="p">,</span><span class="w"> </span><span class="n">ncol</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="c1"># Facet for years</span><span class="w">
    </span><span class="n">coord_equal</span><span class="p">(</span><span class="n">xlim</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">c</span><span class="p">(</span><span class="m">2.5</span><span class="p">,</span><span class="m">54</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="c1"># square tiles</span><span class="w">
    </span><span class="n">scale_x_continuous</span><span class="p">(</span><span class="n">breaks</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">53</span><span class="o">/</span><span class="m">12</span><span class="o">*</span><span class="p">(</span><span class="m">1</span><span class="o">:</span><span class="m">12</span><span class="p">)</span><span class="m">-1.5</span><span class="p">,</span><span class="w"> </span><span class="n">labels</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">c</span><span class="p">(</span><span class="s2">"Jan"</span><span class="p">,</span><span class="s2">"Feb"</span><span class="p">,</span><span class="s2">"Mar"</span><span class="p">,</span><span class="s2">"Apr"</span><span class="p">,</span><span class="s2">"May"</span><span class="p">,</span><span class="s2">"Jun"</span><span class="p">,</span><span class="s2">"Jul"</span><span class="p">,</span><span class="s2">"Aug"</span><span class="p">,</span><span class="s2">"Sep"</span><span class="p">,</span><span class="s2">"Oct"</span><span class="p">,</span><span class="s2">"Nov"</span><span class="p">,</span><span class="s2">"Dec"</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w"> 
    </span><span class="n">my_theme</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w">
    </span><span class="n">scale_fill_gradientn</span><span class="p">(</span><span class="n">colours</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">c</span><span class="p">(</span><span class="s2">"#D61818"</span><span class="p">,</span><span class="w"> </span><span class="s2">"#FFAE63"</span><span class="p">,</span><span class="w"> </span><span class="s2">"#FFFFBD"</span><span class="p">,</span><span class="w"> </span><span class="s2">"#B5E384"</span><span class="p">),</span><span class="w"> </span><span class="n">na.value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"white"</span><span class="p">,</span><span class="w">
                         </span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">legendtitle</span><span class="p">,</span><span class="w">
                         </span><span class="n">guide</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">guide_colorbar</span><span class="p">(</span><span class="w">
                           </span><span class="n">direction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"horizontal"</span><span class="p">,</span><span class="w">
                           </span><span class="n">barheight</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">unit</span><span class="p">(</span><span class="m">2</span><span class="p">,</span><span class="w"> </span><span class="n">units</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"mm"</span><span class="p">),</span><span class="w">
                           </span><span class="n">barwidth</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">unit</span><span class="p">(</span><span class="m">75</span><span class="p">,</span><span class="w"> </span><span class="n">units</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"mm"</span><span class="p">),</span><span class="w">
                           </span><span class="n">title.position</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'top'</span><span class="p">,</span><span class="w">
                           </span><span class="n">title.hjust</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">0.5</span><span class="w">
                         </span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w">
    </span><span class="n">labs</span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">NULL</span><span class="p">,</span><span class="w"> 
         </span><span class="n">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">NULL</span><span class="p">,</span><span class="w"> 
         </span><span class="n">title</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">title</span><span class="p">,</span><span class="w"> 
         </span><span class="n">subtitle</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">subtitle</span><span class="p">)</span><span class="w">
  
  </span><span class="n">my.lines</span><span class="o"><-</span><span class="n">data.frame</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">numeric</span><span class="p">(),</span><span class="w"> 
                       </span><span class="n">y</span><span class="o">=</span><span class="n">numeric</span><span class="p">(),</span><span class="w"> 
                       </span><span class="n">xend</span><span class="o">=</span><span class="n">numeric</span><span class="p">(),</span><span class="w"> 
                       </span><span class="n">yend</span><span class="o">=</span><span class="n">numeric</span><span class="p">(),</span><span class="w"> 
                       </span><span class="n">year</span><span class="o">=</span><span class="n">character</span><span class="p">())</span><span class="w">
  
  </span><span class="k">for</span><span class="p">(</span><span class="n">years</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">levels</span><span class="p">(</span><span class="n">df</span><span class="o">$</span><span class="n">year</span><span class="p">)){</span><span class="w">
    </span><span class="n">df.subset</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">df</span><span class="p">[</span><span class="n">df</span><span class="o">$</span><span class="n">year</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">years</span><span class="p">,]</span><span class="w">
    
    </span><span class="n">y.start</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">df.subset</span><span class="o">$</span><span class="n">dow</span><span class="p">[</span><span class="m">1</span><span class="p">]</span><span class="w">
    </span><span class="n">x.start</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">df.subset</span><span class="o">$</span><span class="n">woy</span><span class="p">[</span><span class="m">1</span><span class="p">]</span><span class="w">
    
    </span><span class="n">x.top.left</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">ifelse</span><span class="p">(</span><span class="n">y.start</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="m">0</span><span class="p">,</span><span class="w"> </span><span class="n">x.start</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">0.5</span><span class="p">,</span><span class="w"> </span><span class="n">x.start</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="m">0.5</span><span class="p">)</span><span class="w">
    </span><span class="n">y.top.left</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="m">7.5</span><span class="w">
    </span><span class="n">x.top.right</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">df.subset</span><span class="o">$</span><span class="n">woy</span><span class="p">[</span><span class="n">nrow</span><span class="p">(</span><span class="n">df.subset</span><span class="p">)]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="m">0.5</span><span class="w">
    </span><span class="n">y.top.right</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="m">7.5</span><span class="w">
    
    </span><span class="n">x.mid.left01</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">x.start</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">0.5</span><span class="w">
    </span><span class="n">y.mid.left01</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="m">7.5</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">y.start</span><span class="w">
    </span><span class="n">x.mid.left02</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">x.start</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="m">0.5</span><span class="w">
    </span><span class="n">y.mid.left02</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="m">7.5</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">y.start</span><span class="w">
    
    </span><span class="n">x.bottom.left</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">x.start</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">0.5</span><span class="w">
    </span><span class="n">y.bottom.left</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="m">0.5</span><span class="w">
    </span><span class="n">x.bottom.right</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">ifelse</span><span class="p">(</span><span class="n">y.start</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="m">6</span><span class="p">,</span><span class="w"> </span><span class="n">df.subset</span><span class="o">$</span><span class="n">woy</span><span class="p">[</span><span class="n">nrow</span><span class="p">(</span><span class="n">df.subset</span><span class="p">)]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="m">0.5</span><span class="p">,</span><span class="w"> </span><span class="n">df.subset</span><span class="o">$</span><span class="n">woy</span><span class="p">[</span><span class="n">nrow</span><span class="p">(</span><span class="n">df.subset</span><span class="p">)]</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">0.5</span><span class="p">)</span><span class="w">
    </span><span class="n">y.bottom.right</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="m">0.5</span><span class="w">
    
    </span><span class="n">my.lines</span><span class="o"><-</span><span class="n">rbind</span><span class="p">(</span><span class="n">my.lines</span><span class="p">,</span><span class="w">
                    </span><span class="n">data.frame</span><span class="p">(</span><span class="n">x</span><span class="w">    </span><span class="o">=</span><span class="w"> </span><span class="nf">c</span><span class="p">(</span><span class="n">x.top.left</span><span class="p">,</span><span class="w"> </span><span class="n">x.bottom.left</span><span class="p">,</span><span class="w"> </span><span class="n">x.mid.left01</span><span class="p">,</span><span class="w"> </span><span class="n">x.top.left</span><span class="p">,</span><span class="w"> </span><span class="n">x.bottom.left</span><span class="p">),</span><span class="w"> 
                               </span><span class="n">y</span><span class="w">    </span><span class="o">=</span><span class="w"> </span><span class="nf">c</span><span class="p">(</span><span class="n">y.top.left</span><span class="p">,</span><span class="w"> </span><span class="n">y.bottom.left</span><span class="p">,</span><span class="w"> </span><span class="n">y.mid.left01</span><span class="p">,</span><span class="w"> </span><span class="n">y.top.left</span><span class="p">,</span><span class="w"> </span><span class="n">y.bottom.left</span><span class="p">),</span><span class="w">
                               </span><span class="n">xend</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">c</span><span class="p">(</span><span class="n">x.top.right</span><span class="p">,</span><span class="w"> </span><span class="n">x.bottom.right</span><span class="p">,</span><span class="w"> </span><span class="n">x.mid.left02</span><span class="p">,</span><span class="w"> </span><span class="n">x.mid.left02</span><span class="p">,</span><span class="w"> </span><span class="n">x.mid.left01</span><span class="p">),</span><span class="w"> 
                               </span><span class="n">yend</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">c</span><span class="p">(</span><span class="n">y.top.right</span><span class="p">,</span><span class="w"> </span><span class="n">y.bottom.right</span><span class="p">,</span><span class="w"> </span><span class="n">y.mid.left02</span><span class="p">,</span><span class="w"> </span><span class="n">y.mid.left02</span><span class="p">,</span><span class="w"> </span><span class="n">y.mid.left01</span><span class="p">),</span><span class="w"> 
                               </span><span class="n">year</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">years</span><span class="p">))</span><span class="w">
    
    </span><span class="c1"># lines to separate months</span><span class="w">
    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">j</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="m">1</span><span class="o">:</span><span class="m">12</span><span class="p">)</span><span class="w">  </span><span class="p">{</span><span class="w">
      </span><span class="n">df.subset.month</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="nf">max</span><span class="p">(</span><span class="n">df.subset</span><span class="o">$</span><span class="n">doy</span><span class="p">[</span><span class="n">df.subset</span><span class="o">$</span><span class="n">month</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">j</span><span class="p">])</span><span class="w">
      </span><span class="n">x.month</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">df.subset</span><span class="o">$</span><span class="n">woy</span><span class="p">[</span><span class="n">df.subset.month</span><span class="p">]</span><span class="w">
      </span><span class="n">y.month</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">df.subset</span><span class="o">$</span><span class="n">dow</span><span class="p">[</span><span class="n">df.subset.month</span><span class="p">]</span><span class="w">
      
      </span><span class="n">x.top.mid</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">x.month</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="m">0.5</span><span class="w">
      </span><span class="n">y.top.mid</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="m">7.5</span><span class="w">
      
      </span><span class="n">x.mid.mid01</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">x.month</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">0.5</span><span class="w">
      </span><span class="n">y.mid.mid01</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="m">7.5</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">y.month</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="w">
      </span><span class="n">x.mid.mid02</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">x.month</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="m">0.5</span><span class="w">
      </span><span class="n">y.mid.mid02</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="m">7.5</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">y.month</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">1</span><span class="w">
      
      </span><span class="n">x.bottom.mid</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">ifelse</span><span class="p">(</span><span class="n">y.month</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="m">6</span><span class="p">,</span><span class="w"> </span><span class="n">x.month</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="m">0.5</span><span class="p">,</span><span class="w"> </span><span class="n">x.month</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="m">0.5</span><span class="p">)</span><span class="w">
      </span><span class="n">y.bottom.mid</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="m">0.5</span><span class="w">
      
      </span><span class="n">my.lines</span><span class="o"><-</span><span class="n">rbind</span><span class="p">(</span><span class="n">my.lines</span><span class="p">,</span><span class="w">
                      </span><span class="n">data.frame</span><span class="p">(</span><span class="n">x</span><span class="w">    </span><span class="o">=</span><span class="w"> </span><span class="nf">c</span><span class="p">(</span><span class="n">x.top.mid</span><span class="p">,</span><span class="w"> </span><span class="n">x.mid.mid01</span><span class="p">,</span><span class="w"> </span><span class="n">x.mid.mid01</span><span class="p">),</span><span class="w"> 
                                 </span><span class="n">y</span><span class="w">    </span><span class="o">=</span><span class="w"> </span><span class="nf">c</span><span class="p">(</span><span class="n">y.top.mid</span><span class="p">,</span><span class="w"> </span><span class="n">y.mid.mid01</span><span class="p">,</span><span class="w"> </span><span class="n">y.mid.mid01</span><span class="p">),</span><span class="w">
                                 </span><span class="n">xend</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">c</span><span class="p">(</span><span class="n">x.mid.mid02</span><span class="p">,</span><span class="w"> </span><span class="n">x.mid.mid02</span><span class="p">,</span><span class="w"> </span><span class="n">x.bottom.mid</span><span class="p">),</span><span class="w"> 
                                 </span><span class="n">yend</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">c</span><span class="p">(</span><span class="n">y.mid.mid02</span><span class="p">,</span><span class="w"> </span><span class="n">y.mid.mid02</span><span class="p">,</span><span class="w"> </span><span class="n">y.bottom.mid</span><span class="p">),</span><span class="w"> 
                                 </span><span class="n">year</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">years</span><span class="p">))</span><span class="w">
      
    </span><span class="p">}</span><span class="w">
    
  </span><span class="p">}</span><span class="w">
  
  </span><span class="c1"># add lines</span><span class="w">
  </span><span class="n">g</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">geom_segment</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="n">my.lines</span><span class="p">,</span><span class="w"> </span><span class="n">aes</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">,</span><span class="n">xend</span><span class="o">=</span><span class="n">xend</span><span class="p">,</span><span class="w"> </span><span class="n">yend</span><span class="o">=</span><span class="n">yend</span><span class="p">),</span><span class="w"> </span><span class="n">lineend</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"square"</span><span class="p">,</span><span class="w"> </span><span class="n">color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"black"</span><span class="p">,</span><span class="w"> </span><span class="n">inherit.aes</span><span class="o">=</span><span class="kc">FALSE</span><span class="p">)</span><span class="w">
  
  </span><span class="nf">return</span><span class="p">(</span><span class="n">g</span><span class="p">)</span><span class="w">
</span><span class="p">}</span><span class="w">
</span>

Example

In the following example I visualise Microsoft’s stock price starting from 2014 with the help of Yahoo Finance API.

<span class="n">stock</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="s2">"MSFT"</span><span class="w">
</span><span class="n">start.date</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="s2">"2014-00-01"</span><span class="w"> </span><span class="c1"># workaround for a small bug with the month extraction</span><span class="w">
</span><span class="n">end.date</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">Sys.Date</span><span class="p">()</span><span class="w">
</span><span class="n">quote</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">paste</span><span class="p">(</span><span class="s2">"http://ichart.finance.yahoo.com/table.csv?s="</span><span class="p">,</span><span class="w">
               </span><span class="n">stock</span><span class="p">,</span><span class="w">
               </span><span class="s2">"&a="</span><span class="p">,</span><span class="w"> </span><span class="n">substr</span><span class="p">(</span><span class="n">start.date</span><span class="p">,</span><span class="m">6</span><span class="p">,</span><span class="m">7</span><span class="p">),</span><span class="w">
               </span><span class="s2">"&b="</span><span class="p">,</span><span class="w"> </span><span class="n">substr</span><span class="p">(</span><span class="n">start.date</span><span class="p">,</span><span class="w"> </span><span class="m">9</span><span class="p">,</span><span class="w"> </span><span class="m">10</span><span class="p">),</span><span class="w">
               </span><span class="s2">"&c="</span><span class="p">,</span><span class="w"> </span><span class="n">substr</span><span class="p">(</span><span class="n">start.date</span><span class="p">,</span><span class="w"> </span><span class="m">1</span><span class="p">,</span><span class="m">4</span><span class="p">),</span><span class="w"> 
               </span><span class="s2">"&d="</span><span class="p">,</span><span class="w"> </span><span class="n">substr</span><span class="p">(</span><span class="n">end.date</span><span class="p">,</span><span class="m">6</span><span class="p">,</span><span class="m">7</span><span class="p">),</span><span class="w">
               </span><span class="s2">"&e="</span><span class="p">,</span><span class="w"> </span><span class="n">substr</span><span class="p">(</span><span class="n">end.date</span><span class="p">,</span><span class="w"> </span><span class="m">9</span><span class="p">,</span><span class="w"> </span><span class="m">10</span><span class="p">),</span><span class="w">
               </span><span class="s2">"&f="</span><span class="p">,</span><span class="w"> </span><span class="n">substr</span><span class="p">(</span><span class="n">end.date</span><span class="p">,</span><span class="w"> </span><span class="m">1</span><span class="p">,</span><span class="m">4</span><span class="p">),</span><span class="w">
               </span><span class="s2">"&g=d&ignore=.csv"</span><span class="p">,</span><span class="w"> </span><span class="n">sep</span><span class="o">=</span><span class="s2">""</span><span class="p">)</span><span class="w">             
</span><span class="n">stock.data</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">read.csv</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span><span class="w"> </span><span class="n">as.is</span><span class="o">=</span><span class="kc">TRUE</span><span class="p">)</span><span class="w">

</span><span class="n">require</span><span class="p">(</span><span class="n">lubridate</span><span class="p">)</span><span class="w">

</span><span class="n">dates</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">ymd</span><span class="p">(</span><span class="n">stock.data</span><span class="o">$</span><span class="n">Date</span><span class="p">)</span><span class="w">
</span><span class="n">values</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">stock.data</span><span class="o">$</span><span class="n">Adj.Close</span><span class="w">

</span><span class="n">calendarHeatmap</span><span class="p">(</span><span class="n">dates</span><span class="p">,</span><span class="w"> </span><span class="n">values</span><span class="p">,</span><span class="w"> </span><span class="n">title</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Microsoft Stock Price"</span><span class="p">,</span><span class="w"> </span><span class="n">subtitle</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Yahoo Finance API"</span><span class="p">,</span><span class="w"> </span><span class="n">legendtitle</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Price"</span><span class="p">)</span><span class="w">
</span>

plot of chunk unnamed-chunk-2

SessionInfo

## R version 3.3.1 (2016-06-21)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows >= 8 x64 (build 9200)
## 
## locale:
## [1] LC_COLLATE=German_Germany.1252  LC_CTYPE=German_Germany.1252   
## [3] LC_MONETARY=German_Germany.1252 LC_NUMERIC=C                   
## [5] LC_TIME=German_Germany.1252    
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] ggplot2_2.2.1   lubridate_1.6.0 knitr_1.14     
## 
## loaded via a namespace (and not attached):
##  [1] Rcpp_0.12.6      digest_0.6.9     assertthat_0.1   grid_3.3.1      
##  [5] plyr_1.8.4       gtable_0.2.0     formatR_1.4      magrittr_1.5    
##  [9] evaluate_0.9     scales_0.4.1     stringi_1.1.1    lazyeval_0.2.0  
## [13] labeling_0.3     tools_3.3.1      stringr_1.0.0    munsell_0.4.3   
## [17] colorspace_1.2-6 tibble_1.1

To leave a comment for the author, please follow the link and comment on their blog: Data Science 42.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)