2017-02-09 9 views
1

다음과 같이 일부 문자 데이터를 숫자로 변환하려고합니다. 데이터는 특별한 캐처 맨과 함께 올 것이므로 나는 그들을 꺼내야 만합니다. 데이터를 std : string으로 변환하여 특수 문자를 검색합니다. 그것은 메모리에 새로운 변수를 만듭니다? 더 좋은 방법이 있는지 알고 싶습니다.Rcpp 메모리 관리

NumericVector converter_ra_(Rcpp::RObject x){ 
    if(x.sexp_type() == STRSXP){ 
    CharacterVector y(x); 
    NumericVector resultado(y.size()); 
    for(unsigned int i = 0; i < y.size(); i++){ 
     std::string ra_string = Rcpp::as<std::string>(y[i]); 
     //std::cout << ra_string << std::endl; 
     double t = 0; 
     int base = 0; 
     for(int j = (int)ra_string.size(); j >= 0; j--){ 
     if(ra_string[j] >= 48 && ra_string[j] <= 57){ 
      t += ((ra_string[j] - '0') * base_m[base]); 
      base++; 
     } 
     } 
     //std::cout << t << std::endl; 
     resultado[i] = t; 
    } 
    return resultado; 
    }else if(x.sexp_type() == REALSXP){ 
    return NumericVector(x); 
    } 
    return NumericVector(); 
} 
+2

먼저 'dput (data_set_here)'를 사용하여 데이터 샘플을 추가하십시오. 둘째, 그렇습니다. 타입이'NumericVector'가 아닌 경우 새로운 메모리 벡터를 할당하려고합니다. – coatless

답변

4

는 메모리에 새로운 변수를 생성합니까?

입력 개체가 실제로 숫자 벡터 (REALSXP)이고 단순히 반환하는 경우 (예 : as<NumericVector>(input)이면 추가 변수가 생성되지 않습니다. 다른 경우에는 물론 새로운 메모리가 반환 된 객체에 할당되어야합니다. 예를 들어,

#include <Rcpp.h> 
using namespace Rcpp; 

// [[Rcpp::export]] 
NumericVector demo(RObject x) { 
    if (x.sexp_type() == REALSXP) { 
     return as<NumericVector>(x); 
    } 

    return NumericVector::create(); 
} 

/*** R 

y <- rnorm(3) 
z <- letters[1:3] 

data.table::address(y) 
# [1] "0x6828398" 

data.table::address(demo(y)) 
# [1] "0x6828398" 

data.table::address(z) 
# [1] "0x68286f8" 

data.table::address(demo(z)) 
# [1] "0x5c7eea0" 

*/ 

나는 그것을 할 수있는 더 좋은 방법이 있는지 알고 싶습니다.

먼저 "더 나은"정의해야

  • 빠른?
  • 적은 메모리를 사용합니까?
  • 몇 줄의 코드가 필요합니까?
  • 더 관용적입니까?

개인적으로, 나는 종종 하나 이상의 다른 것들을 수반하기 때문에 개인적으로 마지막 정의부터 시작하겠다. 예를 들어,이 접근 방식에서 우리는

  • 아니라 로컬
  • 에 의해 결정되는 문자를 제거하기 위해 erase-remove idiom를 사용하는 다른 함수 객체를 정의이를 구현하는 것보다 표준 라이브러리 함수 isdigit에 의존하는 함수 객체 Predicate 정의 Predicate; STRSXPstd::vector<std::string>
  • 통화 std::transform로 변환 - as 계산기 - 필요한 경우,
  • 는 Rcpp 관용구를 사용합니다 (대신에게 자신을 구현하기 위해 노력하는, 다시)를 double에 남아있는 것을 변환 std::atoi를 사용 결과 벡터에이를 변환하는

#include <Rcpp.h> 
using namespace Rcpp; 

struct Predicate { 
    bool operator()(char c) const 
    { return !(c == '.' || std::isdigit(c)); } 
}; 

struct Converter { 
    double operator()(std::string s) const { 
     s.erase(
      std::remove_if(s.begin(), s.end(), Predicate()), 
      s.end() 
     ); 

     return s.empty() ? NA_REAL : std::atof(s.c_str()); 
    } 
}; 

// [[Rcpp::export]] 
NumericVector convert(RObject obj) { 
    if (obj.sexp_type() == REALSXP) { 
     return as<NumericVector>(obj); 
    } 
    if (obj.sexp_type() != STRSXP) { 
     return NumericVector::create(); 
    } 

    std::vector<std::string> x = as<std::vector<std::string> >(obj); 
    NumericVector res(x.size(), NA_REAL); 

    std::transform(x.begin(), x.end(), res.begin(), Converter()); 
    return res; 
} 

테 최소한의 기능이 고통,

x <- c("123 4", "abc 1567.35 def", "abcdef", "") 
convert(x) 
# [1] 1234.00 1567.35  NA  NA 

(y <- rnorm(3)) 
# [1] 1.04201552 -0.08965042 -0.88236960 

convert(y) 
# [1] 1.04201552 -0.08965042 -0.88236960 

convert(list()) 
# numeric(0) 

이 뭔가 노련한 C 또는 C++ 프로그래머가 손을 쓴만큼 성능이 좋은 것인가? 거의 확실하지 않습니다. 그러나 우리는 라이브러리 함수와 일반적인 관용구를 사용했기 때문에 합리적으로 간결하며 버그가 없을 가능성이 높으며 의도는 간략하게도 분명합니다.이 더 필요한 경우 최적화가 이루어질 수는 있지만 벤치마킹 및 프로파일 링을 먼저 수행 할 필요는 없습니다.

+0

이 줄은 어떨까요 : std :: string ra_string = Rcpp :: as (y [i]); STRSXP를 얻으면 std : string으로 변환합니다. 더 많은 메모리가 필요합니까? 답변 해 주셔서 감사합니다. – Gustavo

+0

예'Rcpp :: as '을 호출하면'std :: string'에 메모리를 할당해야합니다. 일반적으로 유형 간의 변환에는 변환하려는 유형에 대해 메모리를 할당해야합니다. 'Rcpp :: as (REALSXP)'와 같이 이런 일이 일어나지 않는 유일한 이유는'NumericVector'가 본질적으로 단지'REALSXP'를 내부적으로 저장하는 래퍼 클래스이기 때문입니다. – nrussell