通过 DataFrame 在另一个内部调用一个 Rcpp 函数

Call one Rcpp function inside another passing through DataFrame

我最近一直在将一些 R 代码转换为 Rcpp 函数。我正在模拟人们将汽车停在停车场。我有一个功能,可以根据他们进入的门和停车场的满满程度来选择一个人停在哪个停车场。

#include <Rcpp.h>
#include <numeric>
#include <chrono>

// [[Rcpp::plugins(cpp11)]]

using namespace Rcpp;
// [[Rcpp::export]]
std::string pickLotcpp(std::string gate,DataFrame dist,DataFrame curr,NumericVector maxDist = 0.005) {
  std::vector<std::string> gates = Rcpp::as<std::vector<std::string> >(dist["inGate"]);
  std::vector<std::string> lots = Rcpp::as<std::vector<std::string> >(dist["lot"]);
  NumericVector d = dist["dist"];

  std::vector<std::string> currLots = Rcpp::as<std::vector<std::string> >(curr["Lot"]);
  NumericVector cap = curr["Cap"];
  NumericVector util = curr["Util"];
  NumericVector percFree = (cap - util)/cap;

  std::vector<std::string> relLot;
  NumericVector relD;
  int n = gates.size();
  for(int i = 0; i < n; i++){
    if(gates[i] == gate){
      if(d[i] <= maxDist[0]){
        relLot.push_back(lots[i]);
        relD.push_back(pow(d[i],-2));
      }
    }
  }

  n = relLot.size();
  int n2 = currLots.size();
  NumericVector relPerc;
  for(int i = 0; i < n; i++){
    for(int j = 0; j < n2; j++){
      if(relLot[i] == currLots[j]){
        relPerc.push_back(percFree[j]);
      }
    }
  }

  relD = relD*relPerc;
  NumericVector csV(relD.size());
  std::partial_sum(relD.begin(), relD.end(), csV.begin());
  NumericVector::iterator mv;
  mv = std::max_element(csV.begin(),csV.end());
  double maxV = *mv;
  unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
  std::mt19937 gen(seed);
  std::uniform_real_distribution<> dis(0, maxV);
  double rv = dis(gen);
  int done = 0;
  int i = 0;
  std::string selGate;
  while(done < 1){
    if(csV[i] >= rv){
      selGate = relLot[i];
      done = 1;
    }
    i++;
  }

  return selGate;
}

在 R 中效果很好:

fakeDist = structure(list(inGate = c("A", "A", "B", "B"), lot = c("Y", "Z", "Y", "Z"), dist = c(0.001, 0.003, 0.003, 0.001)), .Names = c("inGate", "lot", "dist"), row.names = c(NA, 4L), class = c("tbl_df", "tbl", "data.frame"))
fakeStatus = structure(list(Lot = c("Y", "Z"), Cap = c(100, 100), Util = c(0, 0)), .Names = c("Lot", "Cap", "Util"), row.names = c(NA, 2L), class = c("tbl_df", "tbl", "data.frame"))

pickLotcpp("A",fakeDist,fakeStatus)

#> [1] "Y"

现在我正在尝试编写函数,该函数将循环遍历所有门 activity 并按顺序停放人员。所以我有这个 Rcpp 函数:

// [[Rcpp::export]]
List test(DataFrame records, DataFrame currentLoc, DataFrame dist, 
          DataFrame currentStatus, NumericVector times){
  List out(times.size());
  NumericVector recID = records["ID"];
  NumericVector recTime = records["Time"];
  NumericVector recDir = records["Dir"];
  std::vector<std::string> Gate = Rcpp::as<std::vector<std::string> >(records["Gate"]);
  NumericVector currState = currentLoc["State"];
  std::vector<std::string> currLot = Rcpp::as<std::vector<std::string> >(currentLoc["Lot"]);

  out[0] = pickLotcpp(Gate[0],dist,currentStatus);

  return out;
}

这在同一个文件中,在 pickLotcpp 下。它编译得很好,但调用时会导致 R 崩溃。

fakeData = structure(list(ID = c(1, 2, 3), Time = c(1, 2, 3), Dir = c(1, 1, 1), Gate = c("A", "A", "B")), .Names = c("ID", "Time", "Dir", "Gate"), row.names = c(NA, 3L), class = c("tbl_df", "tbl", "data.frame"))
fakeLoc = structure(list(ID = c(1, 2, 3), State = c(0, 0, 0), Lot = c("", "", "")), .Names = c("ID", "State", "Lot"), row.names = c(NA, 3L), class = c("tbl_df", "tbl", "data.frame"))

a = test(fakeData, fakeLoc, fakeDist, fakeStatus, 10)

我已经编写了其他 Rcpp 代码,其中函数调用函数并且它们工作正常。我唯一能想到的是,我将一个作为输入的 DataFrame 直接传递给另一个函数,但我找不到任何说我不能的东西。我不是专业的 C++ 程序员 - 我几周前才开始研究它,这让我很困惑。

如何从 test 传递所需的距离和状态数据帧来调用 pickLotcpp

好像和Rcpp没有关系

你能仔细检查一下行吗

selGate = relLot[i];

relLot 可能为空。