在DataFrame :: create(vec1,vec2 ...)中可以添加多少个向量?

时间:2014-12-09 04:40:34

标签: rcpp

我正在创建一个DataFrame来保存已解析的haproxy http日志文件,其中包含相当多的字段(25 +)。

如果我添加20个以上的向量(每个字段一个),我会收到编译错误:

no matching function call to 'create'

创建方法:

    return DataFrame::create(
      _["clientIp"]     = clientIp,
      _["clientPort"]   = clientPort,
      _["acceptDate"]   = acceptDate,
      _["frontendName"] = frontendName,
      _["backendName"]  = backendName,
      _["serverName"]   = serverName,
      _["tq"]           = tq,
      _["tw"]           = tw,
      _["tc"]           = tc,
      _["tr"]           = tr,
      _["tt"]           = tt,
      _["status_code"]  = statusCode,
      _["bytes_read"]   = bytesRead,

#if CAPTURED_REQUEST_COOKIE_FIELD == 1
      _["capturedRequestCookie"]   = capturedRequestCookie,
#endif     

#if CAPTURED_REQUEST_COOKIE_FIELD == 1
      _["capturedResponseCookie"]   = capturedResponseCookie,
#endif    

      _["terminationState"] = terminationState,
      _["actconn"]          = actconn,
      _["feconn"]           = feconn,
      _["beconn"]           = beconn,
      _["srv_conn"]         = srvConn,
      _["retries"]          = retries,
      _["serverQueue"]      = serverQueue,
      _["backendQueue"]     = backendQueue 
    );

问题

  1. 我是否达到了硬限制?
  2. 是否有解决方法允许我向数据框添加20多个向量?

2 个答案:

答案 0 :(得分:5)

是的,你已达到了一个硬限制 - Rcpp受到C ++ 98标准的限制,这需要明确的代码膨胀才能支持“变量”。参数。本质上,必须为每个使用的create函数生成一个新的重载,并且为了避免阻塞编译器Rcpp,最多只提供20个。

解决方法是使用“构建器”#39; class,您连续添加元素,然后在结尾处转换为DataFrame。这个类的一个简单示例 - 我们创建了一个ListBuilder对象,我们先后为add个新列。尝试使用此文件运行Rcpp::sourceCpp()以查看输出。

#include <Rcpp.h>
using namespace Rcpp;

class ListBuilder {

public:

   ListBuilder() {};
   ~ListBuilder() {};

   inline ListBuilder& add(std::string const& name, SEXP x) {
      names.push_back(name);

      // NOTE: we need to protect the SEXPs we pass in; there is
      // probably a nicer way to handle this but ...
      elements.push_back(PROTECT(x));

      return *this;
   }

   inline operator List() const {
      List result(elements.size());
      for (size_t i = 0; i < elements.size(); ++i) {
         result[i] = elements[i];
      }
      result.attr("names") = wrap(names);
      UNPROTECT(elements.size());
      return result;
   }

   inline operator DataFrame() const {
      List result = static_cast<List>(*this);
      result.attr("class") = "data.frame";
      result.attr("row.names") = IntegerVector::create(NA_INTEGER, XLENGTH(elements[0]));
      return result;
   }

private:

   std::vector<std::string> names;
   std::vector<SEXP> elements;

   ListBuilder(ListBuilder const&) {}; // not safe to copy

};

// [[Rcpp::export]]
DataFrame test_builder(SEXP x, SEXP y, SEXP z) {
   return ListBuilder()
      .add("foo", x)
      .add("bar", y)
      .add("baz", z);
}

/*** R
test_builder(1:5, letters[1:5], rnorm(5))
*/

PS:对于Rcpp11,我们有可变函数,因此删除了限制。

答案 1 :(得分:3)

使用Rcpp的另一种常见方法是根据需要使用包含任意数量的DataFrame对象的外部列表(每个对象受相应标头中通过旧式宏扩展/重复提供的元素数量限制)。

在(未经测试的)代码中:

Rcpp::DataFrame a = Rcpp::DateFrame::create(/* ... */);
Rcpp::DataFrame b = Rcpp::DateFrame::create(/* ... */);
Rcpp::DataFrame c = Rcpp::DateFrame::create(/* ... */);

return Rcpp::List::create(Rcpp::Named("a") = a,
                          Rcpp::Named("b") = b,
                          Rcpp::Named("c") = c);