如何在Rcpp中串联列表

时间:2019-06-05 17:44:30

标签: r rcpp

我想在Rcpp中列出c() 2个列表,但是我正努力获得与R中相同的结构。

这是一些简单的数据+示例:

rlist = list(a = "123")
listadd = list(typ = "fdb")
c(rlist, listadd)

这给了我这个

$a
[1] "123"

$typ
[1] "fdb"

使用Rcpp时,我仅发现push_back或多或少地执行了我想要的操作,但是结构有些不同。我还尝试根据此reference使用emplace_back,但似乎并未在Rcpp中实现。

cppFunction('
List cLists(List x, List y) {
  x.push_back(y);
  return(x);
}')

这给了我

cLists(rlist, listadd)
$a
[1] "123"

[[2]]
[[2]]$typ
[1] "fdb"

基于this question,我知道我可以使用Language("c",x,y).eval();来使用R的c()函数并获得正确的结果,但这似乎不是正确的方法。

所以我想知道如何正确连接Rcpp中的列表?

编辑: 根据@Dirk的评论,我尝试创建一个新列表,并用其他列表元素填充它们,但是随后我松开了元素名称。

cppFunction('
List cLists(List x, List y) {
  int nsize = x.size(); 
  int msize = y.size(); 
  List out(nsize + msize);

  for(int i = 0; i < nsize; i++) {
    out[i] = x[i];
  }
  for(int i = 0; i < msize; i++) {
    out[nsize+i] = y[i];
  }
  return(out);
}')

输出:

cLists(rlist, listadd)
[[1]]
[1] "123"

[[2]]
[1] "fdb"

2 个答案:

答案 0 :(得分:1)

对您的实现而言,性能下降似乎来自将name属性复制到stl字符串向量。您可以像这样避免它:

library(Rcpp)
library(microbenchmark)
cppFunction('
List cLists(List x, List y) {
  int nsize = x.size(); 
  int msize = y.size(); 
  List out(nsize + msize);

  CharacterVector xnames = x.names();
  CharacterVector ynames = y.names();
  CharacterVector outnames(nsize + msize);
  out.attr("names") = outnames;
  for(int i = 0; i < nsize; i++) {
    out[i] = x[i];
    outnames[i] = xnames[i];
  }
  for(int i = 0; i < msize; i++) {
    out[nsize+i] = y[i];
    outnames[nsize+i] = ynames[i];
  }

  return(out);
}')

x <- as.list(runif(1e6)); names(x) <- sample(letters, 1e6, T)
y <- as.list(runif(1e6)); names(y) <- sample(letters, 1e6, T)

microbenchmark(cLists(x,y), c(x,y), times=3)
Unit: milliseconds
         expr      min       lq     mean   median       uq      max neval cld
 cLists(x, y) 31.70104 31.86375 32.09983 32.02646 32.29922 32.57198     3  a 
      c(x, y) 47.31037 53.21409 56.41159 59.11781 60.96220 62.80660     3   b

注意:通过复制到std::string,您还会丢失可能的字符编码信息,而仅使用R / Rcpp保留即可。

答案 1 :(得分:0)

这是我想出的。输出正确,但是不幸的是,它的性能也比R版本低得多。

library(Rcpp)
cppFunction('
List cLists(List x, List y) {
  int nsize = x.size(); 
  int msize = y.size(); 
  List out(nsize + msize);

  CharacterVector xnames = x.names();
  CharacterVector ynames = y.names();

  for(int i = 0; i < nsize; i++) {
    out[i] = x[i];
  }
  for(int i = 0; i < msize; i++) {
    out[nsize+i] = y[i];
  }

  std::vector<std::string> z(x.size() + y.size());
  std::copy(xnames.begin(), xnames.end(), z.begin());
  std::copy(ynames.begin(), ynames.end(), z.begin() + x.size());

  out.attr("names") = z; 

  return(out);
}')

输出:

cLists(rlist, listadd)
$a
[1] "123"

$typ
[1] "fdb"