R cpp функция для подстановки строк - PullRequest
4 голосов
/ 10 января 2020

Мне было интересно, существует ли функция R cpp, которая принимает тип данных Rcpp::String в качестве входных данных и возвращает заданный символ (по индексу) строки. Например, извлечение символа по индексу 0 строки. Это будет эквивалентно методу string::at из заголовка string в c ++. Я написал это:

using namespace Rcpp;
using namespace std;

typedef vector<string> stringList;

int SplitGenotypesA(string s) {
    char a = s.at(0);
    int b = a - '0';
    return b;
}

Но предпочел бы не преобразовывать типы R cpp :: String и std :: string.

Спасибо.

1 Ответ

4 голосов
/ 10 января 2020

Вы можете передать вектор R строк непосредственно в C ++, используя Rcpp::StringVector. Это, очевидно, будет работать и с отдельными элементами.

Получение n-го символа i-го элемента вашего вектора так же просто, как vector[i][n].

Таким образом, без использования std::string вы можете сделать это :

#include<Rcpp.h>

// [[Rcpp::export]]
Rcpp::NumericVector SplitGenotypesA(Rcpp::StringVector R_character_vector)
{
  int number_of_strings = R_character_vector.size();
  Rcpp::NumericVector result(number_of_strings);
  for(int i = 0; i < number_of_strings; ++i)
  {
    char a = R_character_vector[i][0];
    result[i] = a - '0';
  }
  return result;
}

Теперь в R вы можете сделать:

SplitGenotypesA("9C")
# [1] 9

или еще лучше,

SplitGenotypesA(c("1A", "2B", "9C"))
# [1] 1 2 9

Что даже немного быстрее, чем собственный метод R делать то же самое:

microbenchmark::microbenchmark(
  R_method    = as.numeric(substr(c("1A", "2B", "9C"), 1, 1)), 
  Rcpp_method = SplitGenotypesA(c("1A", "2B", "9C")),
  times = 1000)

# Unit: microseconds
#         expr   min    lq     mean median    uq    max neval
#     R_method 3.422 3.765 4.076722  4.107 4.108 46.881  1000
#  Rcpp_method 3.080 3.423 3.718779  3.765 3.765 32.509  1000

...