在R中使用Rcpp与Rcpp相交

时间:2016-11-09 20:52:09

标签: rcpp

我是Rcpp的新手,我正在尝试编写一个简单的函数,它将获取一个字符向量列表(myList)和一个单独的字符向量(vec1),并返回一个列表每个列表向量和vec1之间的交叉点。

我可以很容易地在R中做到这一点:

myList <- list(
                c('apple','banana','orange','pineapple'),
                c('pear','pineapple','watermelon'),
                c('orange','apple','pineapple'),
                NA,
                c('watermelon','lime','apple','banana'))

vec1 <- c('apple','pineapple','banana')

# R implementation
lapply(myList, function(x) intersect(x, vec1))

但我对如何使用Rcpp实现这一点感到困惑。这是我的尝试:

cppFunction('
    List intersectList (List input, StringVector vec) {

        int n = input.size();
        List out(n);

        for (int i = 0; i < n; i++) {

            StringVector sp = Rcpp::as< std::vector<std::string> > (input[i]);

            if (sp.length() > 0) {  
                out[i] = intersect(sp, vec);
            }
        }

        return out;

    }
')

...但是这会导致错误:

Error in sourceCpp(code = code, env = env, rebuild = rebuild, cacheDir = cacheDir,  : 
  Error 1 occurred building shared library.
file1510d6dbd767c.cpp:14:17: error: no viable conversion from 'std::__1::vector<std::__1::basic_string<char>, std::__1::allocator<std::__1::basic_string<char> > >' to 'StringVector' (aka 'Vector<16>')
                        StringVector sp = Rcpp::as< std::vector<std::string> > (input[i]);
                                     ^    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcpp/include/Rcpp/vector/Vector.h:65:5: note: candidate constructor not viable: no known conversion from 'std::__1::vector<std::__1::basic_string<char>, std::__1::allocator<std::__1::basic_string<char> > >' to 'const Rcpp::Vector<16, PreserveStorage> &' for 1st argument
    Vector( const Vector& other){
    ^
/Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcpp/include/Rcpp/vector/Vector.h:73:5: note: candidate constructor not viable: no known conversion from 'std::__1::vector<std::__1::basic_string<char>, std::__1::allocator<std::__1::basic_string<char> > >' to 'SEXP' (aka 'SEXPREC *') for 1st argument
    Vector( SEXP x ) {
    ^
/Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcpp/include/Rcpp/vector/Vector.h:101:5: note: candidate constructor not viable: no known conversion from 'std::__1::vector<std::__1::basic_string<char>, std::__1::allocator<std::__1::basic_string<char> > >' to 'const std::string &' (aka 'const basic_string<char, char_traits<char>, allocator<char> > &') for 1st argument
    Vector( const std::string& st ){
    ^
/Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcpp/include/Rcpp/vector/Vector.h:107:5: note: candidate constructor not viable: no known conversion from 'std::__1::vector<std::__1::basic_string<char>, std::__1::allocator<std::__1::basic_string<char> > >' to 'const char *' for 1st argument
    Vector( const char* st ) {
    ^
/Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcpp/include/Rcpp/vector/Vector.h:128:5: note: candidate constructor not viable: no known conversion from 'std::__1::vector<std::__1::basic_string<char>, std::__1::allocator<std::__1::basic_string<char> > >' to 'const int &' for 1st argument
    Vector( const int& size ) {
    ^
/Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcpp/include/Rcpp/vector/Vector.h:133:5: note: candidate constructor not viable: no known conversion from 'std::__1::vector<std::__1::basic_string<char>, std::__1::allocator<std::__1::basic_string<char> > >' to 'const Rcpp::Dimension &' for 1st argument
    Vector( const Dimension& dims) {
    ^
/Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcpp/include/Rcpp/vector/Vector.h:78:5: note: candidate template ignored: could not match 'GenericProxy' against 'vector'
    Vector( const GenericProxy<Proxy>& proxy ){
    ^
/Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcpp/include/Rcpp/vector/Vector.h:123:42: note: candidate template ignored: disabled by 'enable_if' [with T = std::__1::vector<std::__1::basic_string<char>, std::__1::allocator<std::__1::basic_string<char> > >]
        typename Rcpp::traits::enable_if<traits::is_arithmetic<T>::value, void>::type* = 0) {
                                         ^
/Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcpp/include/Rcpp/vector/Vector.h:146:45: note: candidate template ignored: disabled by 'enable_if' [with T = std::__1::vector<std::__1::basic_string<char>, std::__1::allocator<std::__1::basic_string<char> > >]
           typename Rcpp::traits::enable_if<traits::is_bool<T>::value && RTYPE == LGLSXP, void>::type* = 0) {
                                            ^
/Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcpp/include/Rcpp/vector/Vector.h:162:5: note: candidate template ignored: could not match 'VectorBase' against 'vector'
    Vector( const VectorBase<RTYPE,NA,VEC>& other ) {
    ^
/Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcpp/include/Rcpp/vector/Vector.h:176:5: note: candidate template ignored: could not match 'SingleLogicalResult' against 'vector'
    Vector( const sugar::SingleLogicalResult<NA,T>& obj ) {
    ^
1 error generated.
make: *** [file1510d6dbd767c.o] Error 1

在这种特殊情况下,R实现简单快速,因此可能不需要Rcpp。但我想了解Rcpp实现,因为它可以让我更好地理解如何使用Rcpp处理向量和列表。

2 个答案:

答案 0 :(得分:2)

简言之:

  1. 该函数名为intersect;你的标题谈到intercept。不一样。

  2. intersect()的单元测试是一行的(见下文)。如果我是你,我会从它开始并使用StringVector类型进行尝试。

  3. 您正在StringVectorstd::vector<std::string>之间跳跃。为什么?如果您在StringVector sp = Rcpp::as< std::vector<std::string> > (input[i]);中更改StringVector以使用as<>(),那么您可能会感觉良好。 [未经测试,现在没时间。 ]

  4. 测试功能(包含在文件unitTests/cpp/sugar.cpp中的每个Rcpp版本中:

    // [[Rcpp::export]]
    IntegerVector runit_intersect( IntegerVector x, IntegerVector y){
        return intersect( x, y ) ;
    }
    

答案 1 :(得分:0)

感谢Dirk Eddelbuettel提出以下建议:

> cppFunction('
+   List intersectList (List input, StringVector vec) {
+   
+       int n = input.size();
+       List out(n);
+   
+       for (int i = 0; i < n; i++) {
+           
+           StringVector sp = Rcpp::as< StringVector > (input[i]);
+   
+           if (sp.length() > 0) {  
+               out[i] = intersect(sp, vec);
+           }
+       }
+   
+       return out;
+ 
+   }
+ ')
> 
> myList <- list(
+               c('apple','banana','orange','pineapple'),
+               c('pear','pineapple','watermelon'),
+               c('orange','apple','pineapple'),
+               NA,
+               c('watermelon','lime','apple','banana'))
>               
> vec1 <- c('apple','pineapple','banana')
> 
> intersectList(myList, vec1)
[[1]]
[1] "pineapple" "banana"    "apple"    

[[2]]
[1] "pineapple"

[[3]]
[1] "pineapple" "apple"    

[[4]]
character(0)

[[5]]
[1] "banana" "apple"