How to iterate over an Rcpp DateVector (with example)

In a recent Rcpp project I wanted (in C++) to iterate over the elements of a DateVector. It turns out that my naive approach didn’t work, and it took me a fair bit of Googling to find the answer so I thought it was worth recording. If you’re in a rush you can skip the preamble and jump straight to the solution.

Iterating over DateVectors doesn’t work as expected#

For the sake of this example let’s say I was trying to duplicate lubridate::year(), i.e. given a vector of dates, return a vector containing just the year of those dates. An Rcpp::Date object has a getYear() method, but a DateVector doesn’t have an equivalent. No problem, just loop over the DateVector and call the getYear() method on each, right?

Here’s my first attempt:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
IntegerVector get_years(const DateVector& dates) {
  auto n = dates.length();
  IntegerVector out(n);
  for (auto i = 0; i < n; i++) {
    out[i] = dates[i].getYear();  
  }
  return out;
}

To my surprise this yielded a compiler error saying that the getYear() method doesn’t exist for double objects, which is confusing because I’m working with a vector of Dates, not doubles, aren’t I?

E> get-years.cpp: In function 'Rcpp::IntegerVector get_years(const DateVector&)':
   get-years.cpp:9:23: error: request for member 'getYear' in 
   [...looooong Rcpp class description...]
   which is of non-class type 'const type {aka const double}'
E>      out[i] = dates[i].getYear();
E>                        ^

The solution: create a Date object#

If we explicitly create a Date object first the compiler is perfectly happy; the code below works as expected:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
IntegerVector get_years(const DateVector& dates) {
  auto n = dates.length();
  IntegerVector out(n);
  for (auto i = 0; i < n; i++) {
    Date d = dates[i];
    out[i] = d.getYear();
  }
  return out;
}

An explanation for this behaviour is given in a related StackOverflow question. To quote duckmayr’s answer:

[…] an Rcpp::DateVector is not a vector of Rcpp::Dates, but is a class derived from Rcpp::NumericVector (see here). This makes sense considering R’s own internal treatment of date vectors:

pryr::sexp_type(as.Date("2019/05/04"))
# [1] "REALSXP"

To which Dirk Eddelbuettel, the maintainer of Rcpp, added:

[…] conversion[s] which do require to/from conversion to SEXP “generally work” but the compiler sometimes needs some help. As such the assigning of a DateVector element to a Date makes comparison easier.

This explains the compiler error, but for me it was not intuitive that a DateVector is not the same as a vector of Dates.

duckmeyr’s answer goes on to suggest an alternative:

If what you actually want is a vector of Rcpp::Dates, that can be achieved easily as well using the member function getDates():

// [[Rcpp::export]]
bool dateProb(DateVector dateVec, Date date) {
    Date date2 = dateVec(0);
    std::vector<Date> newdates = dateVec.getDates();
    Rcpp::Rcout << (newdates[0] < date) << "\n";
    return (date2 < date);
}

Hopefully this post was useful to someone, and you found your answer quicker than I did!