├── .Rbuildignore ├── .gitignore ├── traildb_logo_512.png ├── src ├── Makevars ├── RTraildb.h ├── RcppExports.cpp └── rtraildb.cpp ├── NAMESPACE ├── R ├── zzz.R ├── RcppExports.R ├── utils.R ├── summary.R └── read.R ├── man ├── get_dim_traildb.Rd ├── describe_traildb.Rd └── read_traildb.Rd ├── DESCRIPTION ├── README.md └── LICENSE /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.so 2 | *.o 3 | *.a 4 | .Rproj.user 5 | .*.Rproj 6 | -------------------------------------------------------------------------------- /traildb_logo_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/traildb/traildb-r/HEAD/traildb_logo_512.png -------------------------------------------------------------------------------- /src/Makevars: -------------------------------------------------------------------------------- 1 | CXX_STD = CXX11 2 | PKG_CPPFLAGS += -I/usr/local/include 3 | PKG_LIBS += -L/usr/local/lib -ltraildb 4 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(describe_traildb) 4 | export(get_dim_traildb) 5 | export(read_traildb) 6 | import(digest) 7 | importClassesFrom(Rcpp,"C++Object") 8 | useDynLib(RTraildb) 9 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | #'@useDynLib RTraildb 2 | #'@importClassesFrom Rcpp "C++Object" 3 | #'@import digest 4 | .onLoad <- function(libname, pkgname) { } 5 | 6 | .onUnload <- function (libpath) { 7 | gc() # Force garbage collection of existing traildb files 8 | library.dynam.unload("RTraildb", libpath) 9 | } 10 | -------------------------------------------------------------------------------- /man/get_dim_traildb.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/summary.R 3 | \name{get_dim_traildb} 4 | \alias{get_dim_traildb} 5 | \title{get_dim_traildb returns the list of dimensions} 6 | \usage{ 7 | get_dim_traildb(file) 8 | } 9 | \arguments{ 10 | \item{file}{Path to the traildb object.} 11 | } 12 | \value{ 13 | Vector of dimensions 14 | } 15 | \description{ 16 | \code{get_dim_traildb} returns a vector of the dimensions 17 | } 18 | 19 | -------------------------------------------------------------------------------- /man/describe_traildb.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/summary.R 3 | \name{describe_traildb} 4 | \alias{describe_traildb} 5 | \title{Provide a summary of the traildb object} 6 | \usage{ 7 | describe_traildb(file) 8 | } 9 | \arguments{ 10 | \item{file}{Path to the traildb object (tarball will be automatically unpacked)} 11 | } 12 | \value{ 13 | Summary of the traildb object 14 | } 15 | \description{ 16 | \code{describe_traildb} returns a summary of the traildb object 17 | } 18 | 19 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: RTraildb 2 | Type: Package 3 | Title: R Interface to Traildb 4 | Version: 0.1 5 | Date: 2015-12-14 6 | Authors@R: c( 7 | person("Ville", "Tuulos", ,"ville.tuulos@adroll.com", role = "aut"), 8 | person("Asif", "Imran", , "asif.imran@adroll.com", role = c("aut", "cre")), 9 | person("Bryan", "Galvin", , "bryan.galvin@adroll.com", role = "aut"), 10 | person("AdRoll", role = "cph") 11 | ) 12 | Description: More about what it does (maybe more than one line) 13 | License: GPL (>= 2) 14 | Imports: 15 | Rcpp (>= 0.11.6), 16 | stringi 17 | LinkingTo: Rcpp, 18 | BH 19 | RoxygenNote: 5.0.1 20 | -------------------------------------------------------------------------------- /R/RcppExports.R: -------------------------------------------------------------------------------- 1 | # This file was generated by Rcpp::compileAttributes 2 | # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | read_trails_meta <- function(tdbSpec, verbose = FALSE) { 5 | .Call('RTraildb_read_trails_meta', PACKAGE = 'RTraildb', tdbSpec, verbose) 6 | } 7 | 8 | read_trails <- function(tdbSpec, first_trail = 0L, last_trail = 0L, sample = FALSE, fraction = 1.0, start_timestamp = 0L, stop_timestamp = 0L, filter = "", verbose = FALSE) { 9 | .Call('RTraildb_read_trails', PACKAGE = 'RTraildb', tdbSpec, first_trail, last_trail, sample, fraction, start_timestamp, stop_timestamp, filter, verbose) 10 | } 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TrailDB R bindings 2 | ======================== 3 | 4 | ![TrailDB logo](traildb_logo_512.png?raw=true) 5 | 6 | A minimal R binding for traildb C API [TrailDB](http://traildb.io/). The initial 7 | goal for this project was to allow interactive querying of traildb data in a 8 | more R-friendly manner (think dataframes!). 9 | 10 | It has a dependency on the [traildb-cpp](https://github.com/traildb/traildb-cpp) 11 | project. 12 | 13 | How to build 14 | ------------ 15 | 16 | You need to install traildb and traildb-cpp (install the headers in a system-wide location). 17 | 18 | 19 | 20 | ### Build from source 21 | 22 | >> library(devtools) 23 | >> devtools::install_github("traildb/traildb-r") 24 | 25 | 26 | ### Try it out. Use the minimal testfile 27 | 28 | >> library(RTraildb) 29 | >> read_traildb('tdbtest.tdb') 30 | -------------------------------------------------------------------------------- /src/RTraildb.h: -------------------------------------------------------------------------------- 1 | #ifndef RTRAILDB_H_INCLUDED 2 | #define RTRAILDB_H_INCLUDED 3 | 4 | #include 5 | using namespace Rcpp; 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | class TrailDB; 23 | 24 | class RTrailDB { 25 | 26 | public: 27 | RTrailDB(std::string dbpath); 28 | virtual ~RTrailDB(); 29 | static std::shared_ptr Create(Rcpp::List spec); 30 | std::string dbPath_; 31 | 32 | }; 33 | 34 | 35 | std::shared_ptr RTrailDB::Create(Rcpp::List spec) { 36 | std::string filename = as(spec["name"]); 37 | return std::make_shared(filename); 38 | } 39 | 40 | 41 | 42 | #endif //RTRAILDB_H_INCLUDED 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016 AdRoll, Inc. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included 13 | in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | #'@useDynLib RTraildb 2 | #'@importClassesFrom Rcpp "C++Object" 3 | #'@import digest 4 | printf <- function(...) invisible(cat(sprintf(...),"\n",sep="")) 5 | 6 | standardize_ts <- function(ts) { 7 | if(!is.na(ts)) { 8 | if(!inherits(ts, "POSIXct")) { 9 | stop("time must be POSIXct or NA", call. = FALSE) 10 | } 11 | else{return(as.numeric(ts))} 12 | } 13 | else{return(0)} 14 | } 15 | 16 | #https://github.com/hadley/readr/blob/master/R/source.R 17 | standardize_path <- function(path) { 18 | path <- check_path(path) 19 | switch(tools::file_ext(path), 20 | tar = tarfile(path), 21 | path 22 | ) 23 | } 24 | 25 | check_path <- function(path) { 26 | if (file.exists(path)) 27 | return(normalizePath(path, "/", mustWork = FALSE)) 28 | 29 | stop("'", path, "' does not exist", 30 | if (!is_absolute_path(path)) 31 | paste0(" in current working directory ('", getwd(), "')"), 32 | ".", 33 | call. = FALSE 34 | ) 35 | } 36 | 37 | is_absolute_path <- function(path) { 38 | grepl("^(/|[A-Za-z]:|\\\\|~)", path) 39 | } 40 | 41 | tarfile <- function(path) { 42 | message("untar ", path) 43 | files <- utils::untar(path, list=TRUE) 44 | return(tools::file_path_sans_ext(path)) #likely a brittle implementation 45 | } 46 | -------------------------------------------------------------------------------- /R/summary.R: -------------------------------------------------------------------------------- 1 | #'@useDynLib RTraildb 2 | #'@importClassesFrom Rcpp "C++Object" 3 | NULL 4 | 5 | #' Provide a summary of the traildb object 6 | #' 7 | #' \code{describe_traildb} returns a summary of the traildb object 8 | #' 9 | #' @param file Path to the traildb object (tarball will be automatically unpacked) 10 | #' @return Summary of the traildb object 11 | #' @export 12 | describe_traildb <- function(file) { 13 | file <- standardize_path(file) 14 | spec <- list(name=file) 15 | out <- read_trails_meta(spec) 16 | 17 | printf("") 18 | printf(" - Path: %s",file) 19 | printf(' # uuids: %12d',out$number_of_uuids) 20 | printf(' # events: %12d',out$number_of_events) 21 | printf(' # fields: %12d',(out$number_of_dimensions)) 22 | for(i in 1:length(out$dimensions)) { 23 | printf(' # -%-25s %12d',out$dimensions[i],out$dimensions_uniques[i]+1) 24 | } 25 | printf(' \u2265 time: %s',format(as.POSIXct(out$min_timestamp,origin='1970-01-01'),'%Y-%m-%d %H:%M:%S')) 26 | printf(' \u2264 time: %s',format(as.POSIXct(out$max_timestamp,origin='1970-01-01'), '%Y-%m-%d %H:%M:%S')) 27 | } 28 | 29 | #' get_dim_traildb returns the list of dimensions 30 | #' 31 | #' \code{get_dim_traildb} returns a vector of the dimensions 32 | #' 33 | #' @param file Path to the traildb object. 34 | #' @return Vector of dimensions 35 | #' @export 36 | get_dim_traildb <- function(file) { 37 | file <- standardize_path(file) 38 | spec <- list(name=file) 39 | out <- read_trails_meta(spec) 40 | 41 | return(c(out$dimensions,'uuid','timestamp')) 42 | } 43 | -------------------------------------------------------------------------------- /src/RcppExports.cpp: -------------------------------------------------------------------------------- 1 | // This file was generated by Rcpp::compileAttributes 2 | // Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | #include 5 | 6 | using namespace Rcpp; 7 | 8 | // read_trails_meta 9 | List read_trails_meta(List tdbSpec, bool verbose); 10 | RcppExport SEXP RTraildb_read_trails_meta(SEXP tdbSpecSEXP, SEXP verboseSEXP) { 11 | BEGIN_RCPP 12 | Rcpp::RObject __result; 13 | Rcpp::RNGScope __rngScope; 14 | Rcpp::traits::input_parameter< List >::type tdbSpec(tdbSpecSEXP); 15 | Rcpp::traits::input_parameter< bool >::type verbose(verboseSEXP); 16 | __result = Rcpp::wrap(read_trails_meta(tdbSpec, verbose)); 17 | return __result; 18 | END_RCPP 19 | } 20 | // read_trails 21 | RObject read_trails(List tdbSpec, uint32_t first_trail, uint32_t last_trail, bool sample, double fraction, uint32_t start_timestamp, uint32_t stop_timestamp, std::string filter, bool verbose); 22 | RcppExport SEXP RTraildb_read_trails(SEXP tdbSpecSEXP, SEXP first_trailSEXP, SEXP last_trailSEXP, SEXP sampleSEXP, SEXP fractionSEXP, SEXP start_timestampSEXP, SEXP stop_timestampSEXP, SEXP filterSEXP, SEXP verboseSEXP) { 23 | BEGIN_RCPP 24 | Rcpp::RObject __result; 25 | Rcpp::RNGScope __rngScope; 26 | Rcpp::traits::input_parameter< List >::type tdbSpec(tdbSpecSEXP); 27 | Rcpp::traits::input_parameter< uint32_t >::type first_trail(first_trailSEXP); 28 | Rcpp::traits::input_parameter< uint32_t >::type last_trail(last_trailSEXP); 29 | Rcpp::traits::input_parameter< bool >::type sample(sampleSEXP); 30 | Rcpp::traits::input_parameter< double >::type fraction(fractionSEXP); 31 | Rcpp::traits::input_parameter< uint32_t >::type start_timestamp(start_timestampSEXP); 32 | Rcpp::traits::input_parameter< uint32_t >::type stop_timestamp(stop_timestampSEXP); 33 | Rcpp::traits::input_parameter< std::string >::type filter(filterSEXP); 34 | Rcpp::traits::input_parameter< bool >::type verbose(verboseSEXP); 35 | __result = Rcpp::wrap(read_trails(tdbSpec, first_trail, last_trail, sample, fraction, start_timestamp, stop_timestamp, filter, verbose)); 36 | return __result; 37 | END_RCPP 38 | } 39 | -------------------------------------------------------------------------------- /man/read_traildb.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/read.R 3 | \name{read_traildb} 4 | \alias{read_traildb} 5 | \title{Read a traildb file into a data frame} 6 | \usage{ 7 | read_traildb(file, first = 0, last = 0, sample = FALSE, p = 1, 8 | startTime = NA, stopTime = NA) 9 | } 10 | \arguments{ 11 | \item{file}{Path to the traildb object. If a tarball is provided, it will be unpacked 12 | first} 13 | 14 | \item{first}{The starting trail number. The default first is 0 implying it starts 15 | from beginning of the trails but you can use any positive integer that is less than 16 | the total number of trails in the traildb object. Use \code{describe_traildb} to 17 | query the number of trails.} 18 | 19 | \item{last}{The last trail number. The default is 100 implying it will only load 100 20 | trails by default. You can make it any positive integer larger than first and less than 21 | the total number of trails in the traildb object.} 22 | 23 | \item{sample}{Uniformly sample the trails? By default, there are no sampling but you can 24 | enable sampling by setting sample = \code{TRUE}.} 25 | 26 | \item{p}{Sampling ratio. In case, \code{sample} is set to \code{TRUE}, you can specify 27 | the fraction of trails that goes into the output data frame} 28 | 29 | \item{startTime}{Filter all trails before startTime. It accepts unix a POSIXct object 30 | By default, no trails are filtered by timestamp} 31 | 32 | \item{stopTime}{Filter all trails after (including) stopTimestamp. It acceps POSIXct 33 | object. By default, no trails are filtered by timestamp.} 34 | 35 | \item{filter}{Only keep trails matching filter type. Default is none} 36 | 37 | \item{verbose}{Produce debugging logs to the screen} 38 | } 39 | \value{ 40 | A data frame. 41 | } 42 | \description{ 43 | \code{read_traildb} creates a dataframe from the traildb object 44 | } 45 | \examples{ 46 | # Read from a path 47 | read_traildb('/mnt/emails') 48 | 49 | # Or apply type filters 50 | read_traildb('/mnt/emails', filter='personal') 51 | 52 | # Or apply filters on timestamp 53 | read_traildb('/mnt/emails', 54 | startTime=as.POSIXct('2015-10-12',origin='1970-01-01'), 55 | stopTime=as.POSIXct('2015-10-22',origin='1970-01-01')) 56 | } 57 | 58 | -------------------------------------------------------------------------------- /R/read.R: -------------------------------------------------------------------------------- 1 | #'@useDynLib RTraildb 2 | #'@importClassesFrom Rcpp "C++Object" 3 | NULL 4 | 5 | #' Read a traildb file into a data frame 6 | #' 7 | #' \code{read_traildb} creates a dataframe from the traildb object 8 | #' 9 | #' @param file Path to the traildb object. If a tarball is provided, it will be unpacked 10 | #' first 11 | #' @param first The starting trail number. The default first is 0 implying it starts 12 | #' from beginning of the trails but you can use any positive integer that is less than 13 | #' the total number of trails in the traildb object. Use \code{describe_traildb} to 14 | #' query the number of trails. 15 | #' @param last The last trail number. The default is 100 implying it will only load 100 16 | #' trails by default. You can make it any positive integer larger than first and less than 17 | #' the total number of trails in the traildb object. 18 | #' @param sample Uniformly sample the trails? By default, there are no sampling but you can 19 | #' enable sampling by setting sample = \code{TRUE}. 20 | #' @param p Sampling ratio. In case, \code{sample} is set to \code{TRUE}, you can specify 21 | #' the fraction of trails that goes into the output data frame 22 | #' @param startTime Filter all trails before startTime. It accepts unix a POSIXct object 23 | #' By default, no trails are filtered by timestamp 24 | #' @param stopTime Filter all trails after (including) stopTimestamp. It acceps POSIXct 25 | #' object. By default, no trails are filtered by timestamp. 26 | #' @param filter Only keep trails matching filter type. Default is none 27 | #' @param verbose Produce debugging logs to the screen 28 | #' @return A data frame. 29 | #' @export 30 | #' @examples 31 | #' # Read from a path 32 | #' read_traildb('/mnt/emails') 33 | #' 34 | #' # Or apply type filters 35 | #' read_traildb('/mnt/emails', filter='personal') 36 | #' 37 | #' # Or apply filters on timestamp 38 | #' read_traildb('/mnt/emails', 39 | #' startTime=as.POSIXct('2015-10-12',origin='1970-01-01'), 40 | #' stopTime=as.POSIXct('2015-10-22',origin='1970-01-01')) 41 | read_traildb <- function(file, 42 | first = 0, last = 0, 43 | sample = FALSE, p = 1.0, 44 | startTime=NA, stopTime=NA) { 45 | 46 | if(sample & abs(p) > 1) { 47 | stop('Sample fraction must be between 0 and 1', call.=FALSE) 48 | } 49 | 50 | startTime <- standardize_ts(startTime) 51 | stopTime <- standardize_ts(stopTime) 52 | 53 | file <- standardize_path(file) 54 | spec <- list(name=file) 55 | 56 | out <- read_trails(spec, 57 | first_trail=first, 58 | last_trail=last, 59 | sample=sample, 60 | frac=p, 61 | start_timestamp=startTime, stop_timestamp=stopTime) 62 | out 63 | } 64 | -------------------------------------------------------------------------------- /src/rtraildb.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "RTraildb.h" 5 | 6 | using namespace Rcpp; 7 | 8 | // [[Rcpp::export]] 9 | List read_trails_meta(List tdbSpec, bool verbose = false) { 10 | auto tdb = RTrailDB::Create(tdbSpec); 11 | std::vector fnames = tdb->GetDimNames(); 12 | std::vector fsize; 13 | for(auto it = fnames.begin(); it != fnames.end(); ++it) { 14 | fsize.push_back(tdb->GetFieldSize(*it)); 15 | } 16 | 17 | return List::create( 18 | _["number_of_uuids"] = tdb->GetNumberOfUUIDs(), 19 | _["number_of_events"] = tdb->GetNumberOfEvents(), 20 | _["number_of_dimensions"] = tdb->GetNumberOfFields(), 21 | _["dimensions"] = tdb->GetDimNames(), 22 | _["dimensions_uniques"] = fsize, 23 | _["min_timestamp"] = tdb->GetMinTimestamp(), 24 | _["max_timestamp"] = tdb->GetMaxTimestamp() 25 | ); 26 | } 27 | 28 | // The following will return a data frame object 29 | // [[Rcpp::export]] 30 | RObject read_trails(List tdbSpec, 31 | uint32_t first_trail = 0, 32 | uint32_t last_trail = 0, 33 | bool sample = false, 34 | double fraction = 1.0, 35 | uint32_t start_timestamp = 0, 36 | uint32_t stop_timestamp = 0, 37 | std::string filter = "", 38 | bool verbose=false) { 39 | 40 | auto tdb = RTrailDB::Create(tdbSpec); 41 | 42 | //sanity checks 43 | if(sample && (fraction < 0 || fraction > 1)) { 44 | Rcpp::stop("fraction must be within 0 and 1"); 45 | } 46 | 47 | if(first_trail > last_trail) { 48 | Rcpp::stop("last_trail must be equal to or larger than first_trail"); 49 | } 50 | 51 | if (start_timestamp > stop_timestamp) { 52 | Rcpp::stop("stop_timestamp must be equal to or larger than start_timestamp"); 53 | } 54 | 55 | bool doFilterTrail = false; 56 | if (first_trail != 0 | last_trail != 0) { 57 | doFilterTrail = true; 58 | } 59 | 60 | bool doFilterTimestamp = false; 61 | if (start_timestamp != 0 | stop_timestamp != 0) { 62 | doFilterTimestamp = true; 63 | } 64 | 65 | bool doFilterType = false; 66 | if (filter.compare("")) { 67 | doFilterType = true; 68 | } 69 | 70 | 71 | // Strategy is to fill columns into corresponding vectors 72 | std::vector vDimNames = tdb->GetDimNames(); 73 | std::vector > colVector(vDimNames.size()); 74 | std::vector vuuids; 75 | std::vector vts; 76 | 77 | uint64_t tot_uuids = tdb->GetNumberOfUUIDs(); 78 | 79 | // Process all trails if not stated otherwise 80 | if (!doFilterTrail) { 81 | last_trail = tot_uuids; 82 | } 83 | 84 | for (uint64_t num = first_trail; num < last_trail; ++num) { 85 | auto eventList = tdb->LoadEvents(num); 86 | 87 | if (num % 5000 == 0) 88 | Rcpp::checkUserInterrupt(); 89 | 90 | if (sample && R::runif(0,1) >= fraction) continue; 91 | 92 | EventList::EventIterator evtIter; 93 | 94 | //Number of trails for current uuid 95 | uint32_t evtSize = eventList->GetSize(); 96 | 97 | for (evtIter = eventList->EventsBegin(); 98 | evtIter != eventList->EventsEnd(); 99 | ++evtIter) { 100 | 101 | uint32_t ts = evtIter->GetTimestamp(); 102 | 103 | if (doFilterTimestamp && 104 | (ts < start_timestamp || ts > stop_timestamp )) continue; 105 | 106 | if (doFilterType && (filter.compare(evtIter->GetEventType())) ) continue; 107 | 108 | vuuids.push_back(tdb->GetHexUUIDByInd(num)); 109 | vts.push_back(ts); 110 | 111 | int nd = 0; 112 | for(std::vector::iterator it = vDimNames.begin(); 113 | it != vDimNames.end(); 114 | ++it ) { 115 | if((*it).compare("time")) { 116 | colVector[nd].push_back(evtIter->GetTrail(*it)); 117 | } 118 | else{ 119 | colVector[nd].push_back(""); 120 | } 121 | ++nd; 122 | } 123 | } 124 | } 125 | 126 | //Set the column names 127 | std::vector colNames(2 + vDimNames.size()); 128 | List out = List(2 + vDimNames.size()); 129 | out[0] = vuuids; colNames[0] = "uuid"; 130 | out[1] = vts; colNames[1] = "timestamp"; 131 | for (int k = 0; k < vDimNames.size(); ++k) { 132 | out[k+2] = colVector[k]; 133 | colNames[k+2] = vDimNames[k]; 134 | } 135 | 136 | out.attr("row.names") = IntegerVector::create(NA_INTEGER, -(vuuids.size())); 137 | out.attr("names") = colNames; 138 | out.attr("class") = CharacterVector::create("tbl_df", "tbl", "data.frame"); 139 | 140 | return out; 141 | 142 | } 143 | --------------------------------------------------------------------------------