如何在 rcpp 函数中同时输入字符和数字输入向量?

问题描述 投票:0回答:0

我正在摆弄下面的 Rcpp 代码,它的工作方式类似于 R 的 expand.grid()。目标是采用未知数量的任何数据类的输入向量,并输出所有输入的组合。例如,给定

a<-c(1,2)
b<-c(3,4,5)
,函数
combine_vectors(list(a,b))
返回:

  v1 v2
1  1  3
2  1  4
3  1  5
4  2  3
5  2  4
6  2  5 

我让它为数字输入向量工作,但我终究无法弄清楚如何处理字符串和数字向量。看来我需要做的关键改变是

std::vector<std::vector<int>*> combo_vectors;
是通用的(而不是
<int>
)或根据大小写切换。理想情况下,我想在 C++ 中进行类型检查。

    #include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
DataFrame combine_vectors(List vectors) {
  int num_vectors = vectors.length();
  
  std::vector<int> indices(num_vectors, 0);
  std::vector<std::vector<int>*> combo_vectors;
  
  for (int i = 0; i < num_vectors; i++) {
    combo_vectors.push_back(new std::vector<int>());
  }
  
  bool done = false;
  while (!done) {
    for (int i = 0; i < num_vectors; i++) {
      SEXP vector = vectors[i];
      switch (TYPEOF(vector)) {
        case INTSXP:
          combo_vectors[i]->push_back(IntegerVector(vector)[indices[i]]);
        break;
        case REALSXP:
          combo_vectors[i]->push_back(NumericVector(vector)[indices[i]]);
        break;
        default:
          Rcpp::stop("unsupported vector type");
      }
    }
    
    int i = num_vectors - 1;
    while (i >= 0) {
      indices[i]++;
      if (indices[i] == Rf_length(vectors[i])) {
        indices[i] = 0;
        i--;
      } else {
        break;
      }
    }
    if (i < 0) {
      done = true;
    }
  }
  
  int num_combos = combo_vectors[0]->size();
  List output(num_vectors);
  CharacterVector col_names(num_vectors);
  
  for (int i = 0; i < num_vectors; i++) {
    switch (TYPEOF(vectors[i])) {
      case INTSXP: {
        IntegerVector col(num_combos);
        for (int j = 0; j < num_combos; j++) {
          col[j] = (*combo_vectors[i])[j];
        }
        output[i] = col;
        break;
      }
      case REALSXP: {
        NumericVector col(num_combos);
        for (int j = 0; j < num_combos; j++) {
          col[j] = (*combo_vectors[i])[j];
        }
        output[i] = col;
        break;
      }
      default:
        Rcpp::stop("unsupported vector type");
    }
    
    col_names[i] = std::string("v") + std::to_string(i + 1);
    delete combo_vectors[i];
  }
  
  output.attr("names") = col_names;
  DataFrame df(output);
  
  return df;
}

编辑: 我想我的问题是如何添加字符串向量?当我为 STRSXP 添加大小写切换时,我收到错误消息“没有匹配函数来调用‘push_back(Rcpp::Vector<16>::Proxy)”这是无效代码。

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
DataFrame combine_vectors1(List vectors) {
  int num_vectors = vectors.length();
  
  std::vector<int> indices(num_vectors, 0);
  std::vector <std::vector<int>*>combo_vectors;
  
  for (int i = 0; i < num_vectors; i++) {
    combo_vectors.push_back(new std::vector<int>());
  }
  
  bool done = false;
  while (!done) {
    for (int i = 0; i < num_vectors; i++) {
      SEXP vector = vectors[i];
      switch (TYPEOF(vector)) {
      case INTSXP:
        combo_vectors[i]->push_back(IntegerVector(vector)[indices[i]]);
        break;
      case REALSXP:
        combo_vectors[i]->push_back(NumericVector(vector)[indices[i]]);
        break;
      case STRSXP:
        combo_vectors[i]->push_back(CharacterVector(vector)[indices[i]]);
        break;
      default:
        Rcpp::stop("unsupported vector type");
      }
    }
    
    int i = num_vectors - 1;
    while (i >= 0) {
      indices[i]++;
      if (indices[i] == Rf_length(vectors[i])) {
        indices[i] = 0;
        i--;
      } else {
        break;
      }
    }
    if (i < 0) {
      done = true;
    }
  }
  
  int num_combos = combo_vectors[0]->size();
  List output(num_vectors);
  CharacterVector col_names(num_vectors);
  
  for (int i = 0; i < num_vectors; i++) {
    switch (TYPEOF(vectors[i])) {
    case INTSXP: {
      IntegerVector col(num_combos);
      for (int j = 0; j < num_combos; j++) {
        col[j] = (*combo_vectors[i])[j];
      }
      output[i] = col;
      break;
    }
    case REALSXP: {
      NumericVector col(num_combos);
      for (int j = 0; j < num_combos; j++) {
        col[j] = (*combo_vectors[i])[j];
      }
      output[i] = col;
      break;
    }
    case STRSXP: {
      CharacterVector col(num_combos);
      for (int j = 0; j < num_combos; j++) {
        col[j] = (*combo_vectors[i])[j];
      }
      output[i] = col;
      break;
    }
    default:
      Rcpp::stop("unsupported vector type");
    }
    
    col_names[i] = std::string("v") + std::to_string(i + 1);
    delete combo_vectors[i];
  }
  
  output.attr("names") = col_names;
  DataFrame df(output);
  
  return df;
c++ r rcpp
© www.soinside.com 2019 - 2024. All rights reserved.