0

I wrote a C++ function to convert an arbitrary 'data.frame' passed down from R (via Rcpp) to a 'CharacterMatrix'. So far, the function is stored in a file named "df2String.cpp" which looks like this

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
CharacterMatrix df2String(DataFrame x) {

  int nCols = x.size();
  CharacterVector chContents = as<CharacterVector>(x[1]);

  int nRows = chContents.size();
  CharacterMatrix chOut(nRows, nCols);

  for (int i = 0; i < nCols; i++) {
    chContents = as<CharacterVector>(x[i]);
    chOut(_, i) = chContents;
  }

  return chOut;
}

and yields fine results at least most of the time, e.g.

library(Rcpp)
sourceCpp("df2String.cpp")

df2String(beaver1)[1:5, ]

     [,1]  [,2]  [,3]    [,4]
[1,] "346" "840" "36.33" "0" 
[2,] "346" "850" "36.34" "0" 
[3,] "346" "900" "36.35" "0" 
[4,] "346" "910" "36.42" "0" 
[5,] "346" "920" "36.55" "0"


However, when at least one column in the specified 'data.frame' is of class 'POSIX*', I get the below error message.
## add 'POSIX*' column
beaver1.1 <- beaver1
beaver1.1$time <- formatC(beaver1.1$time, flag = "0", width = 4)
beaver1.1$year <- 1990

beaver1.1$datetime <- paste(beaver1.1$year, beaver1.1$day, beaver1.1$time)
beaver1.1$datetime <- strptime(beaver1.1$datetime, format = "%Y %j %H%M")

df2String(beaver1.1)

Error in eval(substitute(expr), envir, enclos) : not compatible with STRSXP

Being rather a novice to Rcpp (or C++), I'd be thankful for any advice on how to make the C++ function compatible to 'POSIX*'. Right now, I catch 'POSIX*' columns on the R side and convert them to 'character' prior to passing the object on to my custom C++ function, but this doesn't seem very convenient to me.

fdetsch
  • 5,239
  • 3
  • 30
  • 58
  • 1
    Does this happen with both "POSIXlt" and "POSIXct"? "POSIXct" is a "double", so, I guess, you get a formatted number returned? "POSIXlt" is a "list" internally and, presumably, is not handled in rcpp (as a "list" to "character" conversion). Those classes have specific `as.character` method and to simulate an R-like coercion, you'd have to either convert on R side (as currently doing) or build and evaluate a `as.character(my_POSIXlt)` call in rcpp. – alexis_laz Nov 21 '16 at 12:27
  • Thanks for the hint @alexis_laz. Indeed, the function works with 'POSIXct' objects and fails for 'POSIXlt' only. – fdetsch Nov 21 '16 at 14:24

1 Answers1

1

You are relying on automatic conversion of whatever comes in to character via the as<CharacterVector>() conversion.

You are now discovering that it does not work for datetime objects. Welcome to working with types.

You will need to add a branch in your code which detects the type, does what you currently do for integer and numeric vectors, but formats the datetime to string.

There are other answers here showing this: this is but one. We also have one at the Rcpp Gallery.

Community
  • 1
  • 1
Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725