将 lambda 函数应用于 `RcppArmadillo` 中的 `arma::cube`

Posted

技术标签:

【中文标题】将 lambda 函数应用于 `RcppArmadillo` 中的 `arma::cube`【英文标题】:Apply lambda function to `arma::cube` in `RcppArmadillo` 【发布时间】:2020-12-02 08:48:11 【问题描述】:

我尝试使用RcppArmadillo 计算数组每个切片的 Frobenious 范数 (arma::cube)。文件cxxFuns.cpp 中的示例代码如下所示。

// [[Rcpp::depends(RcppArmadillo)]]
#include "RcppArmadillo.h"

// [[Rcpp::export]]
arma::vec array_norm (arma::cube & x) 
    arma::vec out = x.each_slice([](arma::mat& x0) return arma::norm(x0, "fro") ;) ;
    return out ;


cpp文件编译成功后,函数array_norm抛出异常:

set.seed(2020)
Rcpp::sourceCpp('cxxFuns.cpp')
x <- array(rnorm(3*4*5), 3:5)
array_norm(x)
#> error: copy into matrix: can't interpret cube with dimensions 3x4x5 as a vector
#> Error in array_norm(x) : 
#>   copy into matrix: can't interpret cube with dimensions 3x4x5 as a vector

由reprex package 创建于 2020-12-02 (v0.3.0)

【问题讨论】:

【参考方案1】:

这实际上是来自 Armadillo 的错误消息,因为您的逻辑还存在问题——结果不是向量。你可以通过改成这个(独立的,一个非常好的 Rcpp 技巧)代码来看到:

代码

// [[Rcpp::depends(RcppArmadillo)]]
#include "RcppArmadillo.h"

// [[Rcpp::export]]
bool array_norm (arma::cube & x) 
    auto out = x.each_slice([](arma::mat& x0) return arma::norm(x0, "fro") ;) ;
    out.print("out");
    return true;


/*** R
set.seed(2020)
x <- array(rnorm(3*4*5), 3:5)
array_norm2(x)
*/

输出

> Rcpp::sourceCpp("~/git/***/65104769/answer.cpp")

> set.seed(2020)

> x <- array(rnorm(3*4*5), 3:5)

> array_norm2(x)
out
[cube slice 0]
   0.3770  -1.1304   0.9391   0.1174
   0.3015  -2.7965  -0.2294  -0.8531
  -1.0980   0.7206   1.7591   0.9093

[cube slice 1]
   1.1964   1.8000  -2.2890   1.0982
  -0.3716   1.7040   0.0583   0.3182
  -0.1233  -3.0388   2.1744  -0.0731

[cube slice 2]
   0.8343   0.9367  -0.8125   2.4354
   0.1988  -0.1474  -0.7437   0.3881
   1.2978   0.1104   1.0953   0.2906

[cube slice 3]
  -0.2856   0.4472  -0.3010   0.2531
   0.0760   0.9085  -0.7260  -0.3707
  -0.5603  -0.5051  -1.1801   0.0222

[cube slice 4]
   0.6600   0.6014   0.1188  -1.3283
   0.4888  -0.6738   0.1212  -0.5669
  -0.1888   0.4761  -0.1860   0.5788

[1] TRUE

【讨论】:

我总觉得 Rcpp* 函数中的 for-loop 很冗长,虽然它很快。在这个玩具示例中,有什么方法可以提取 lambda 函数的结果吗?

以上是关于将 lambda 函数应用于 `RcppArmadillo` 中的 `arma::cube`的主要内容,如果未能解决你的问题,请参考以下文章

在 pandas 中将 lambda 函数应用于列失败

使用 Lambda 函数 Pandas 设置列值

使用 Terraform 将自动缩放配置应用于 lambda 预置并发

熊猫将 lambda 应用于整个数据框 [重复]

将 Lambda 应用于返回另一个列表的列表的 Java 8 惯用方法?

将 functools.lru_cache 应用于 lambda