A simple RcppArmadillo index issue - r

I'm coding with RcppArmadillo and got stuck with a very basic question. Suppose I have a vector "v", and I want to take its first 10 elements, like in R: v[1:10]. Since 1:10 doesn't work in RcppArmadillo, I tried v.elem(seq_len(10)), but it didn't work. Any hint?

Assuming you're taking about an arma::vec, this should work:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::vec f(const arma::vec & v, int first, int last) {
arma::vec out = v.subvec(first, last);
return out;
}
/*** R
f(11:20, 3, 6)
*/
Note that this uses zero-based indexing (11 is the 0th element of the vector). Coerce to NumericVector as desired.
When source'ed into R, the code is compiled, linked, loaded and the embedded example is executed:
R> sourceCpp("/tmp/armaEx.cpp")
R> f(11:20, 3, 6)
[,1]
[1,] 14
[2,] 15
[3,] 16
[4,] 17
R>
So it all really is _just one call to subvec(). See the Armadillo documentation for more.

Related

Using sample() from within Rcpp

I have a matrix containing probabilities, with each of the four columns corresponding to a score (an integer in sequence from 0 to 4). I want to sample a single score for each row using the probabilities contained in that row as sampling weights. In rows where some columns do not contain probabilities (NAs instead), the sampling frame is limited to the columns (and their corresponding scores) which do (e.g. for a row with 0.45,0.55,NA,NA, either 0 or 1 would be sampled). However, I get this error (followed by several others), so how can I make it work?:
error: no matching function for call to 'as<Rcpp::IntegerVector>(Rcpp::Matrix<14>::Sub&)'
score[i] = sample(scrs,1,true,as<IntegerVector>(probs));
Existing answers suggest RcppArmadillo is the solution but I can't get that to work either. If I add:
require(RcppArmadillo)
before the cppFunction and
score[i] = Rcpp::RcppArmadillo::sample(scrs,1,true,probs);
in place of the existing sample() statement, I get:
error: 'Rcpp::RcppArmadillo' has not been declared
score[i] = Rcpp::RcppArmadillo::sample(scrs,1,true,probs);
Or if I also include,
#include <RcppArmadilloExtensions/sample.h>
at the top, I get:
fatal error: RcppArmadilloExtensions/sample.h: No such file or directory
#include <RcppArmadilloExtensions/sample.h>
Reproducible code:
p.vals <- matrix(c(0.44892077,0.55107923,NA,NA,
0.37111195,0.62888805,NA,NA,
0.04461714,0.47764478,0.303590351,1.741477e-01,
0.91741642,0.07968127,0.002826406,7.589714e-05,
0.69330800,0.24355559,0.058340934,4.795468e-03,
0.43516823,0.43483784,0.120895859,9.098067e-03,
0.73680809,0.22595438,0.037237525,NA,
0.89569365,0.10142719,0.002879163,NA),nrow=8,ncol=4,byrow=TRUE)
step.vals <- c(1,1,3,3,3,3,2,2)
require(Rcpp)
cppFunction('IntegerVector scores_cpp(NumericMatrix p, IntegerVector steps){
int prows = p.nrow();
IntegerVector score(prows);
for(int i=0;i<prows;i++){
int step = steps[i];
IntegerVector scrs = seq(0,step);
int start = 0;
int end = step;
NumericMatrix::Sub probs = p(Range(i,i),Range(start,end));
score[i] = sample(scrs,1,true,probs);
}
return score;
}')
test <- scores_cpp(p.vals,step.vals)
test
Note: the value of step.vals for each row is always equal to the number of columns containing probabilities in that row -1. So passing the step.values to the function may be extraneous.
You may be having a 'forest for the trees' moment here. The RcppArmadillo unit tests actually provide a working example. If you look at the source file inst/tinytest/test_sample.R, it has a simple
Rcpp::sourceCpp("cpp/sample.cpp")
and in the that file inst/tinytest/cpp/sample.cpp we have the standard
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <RcppArmadilloExtensions/sample.h>
to a) tell R to look at RcppArmadillo header directories and b) include the sampler extensions. This is how it works, and this has been documented to work for probably close to a decade.
As an example I can just do (in my $HOME directory containing git/rcpparmadillo)
> Rcpp::sourceCpp("git/rcpparmadillo/inst/tinytest/cpp/sample.cpp")
> set.seed(123)
> csample_integer(1:5, 10, TRUE, c(0.4, 0.3, 0.2, 0.05, 0.05))
[1] 1 3 2 3 4 1 2 3 2 2
>
The later Rcpp addition works the same way, but I find working with parts of matrices to be more expressive and convenient with RcppArmadillo.
Edit: Even simpler for anybody with the RcppArmadillo package installed:
< library(Rcpp)
> sourceCpp(system.file("tinytest","cpp","sample.cpp", package="RcppArmadillo"))
> set.seed(123)
> csample_integer(1:5, 10, TRUE, c(0.4, 0.3, 0.2, 0.05, 0.05))
[1] 1 3 2 3 4 1 2 3 2 2
>
Many thanks for the pointers. I also had some problems with indexing the matrix, so that part is changed, too. The following code works as intended (using sourceCpp()):
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <RcppArmadilloExtensions/sample.h>
using namespace Rcpp;
// [[Rcpp::export]]
IntegerVector scores_cpp(NumericMatrix p, IntegerVector steps){
int prows = p.nrow();
IntegerVector score(prows);
for(int i=0;i<prows;i++){
int step = steps[i];
IntegerVector scrs = seq(0,step);
NumericMatrix probs = p(Range(i,i),Range(0,step));
IntegerVector sc = RcppArmadillo::sample(scrs,1,true,probs);
score[i] = sc[0];
}
return score;
}

Is there any way in which to make an Infix function using sourceCpp()

I was wondering whether it is possible to make an infix function, e.g. A %o% B with Rcpp.
I know that this is possible using the inline package, but have yet been able to find a method for doing this when using sourceCpp().
I have made the following infix implementation of %o% / outer() when arguments are sure to be vectors using RcppEigen and inline:
`%op%` <- cxxfunction(signature(v1="NumericVector",
v2="NumericVector"),
plugin = "RcppEigen",
body = c("
NumericVector xx(v1);
NumericVector yy(v2);
const Eigen::Map<Eigen::VectorXd> x(as<Eigen::Map<Eigen::VectorXd> >(xx));
const Eigen::Map<Eigen::VectorXd> y(as<Eigen::Map<Eigen::VectorXd> >(yy));
Eigen::MatrixXd op = x * y.transpose();
return Rcpp::wrap(op);
"))
This can easily be implemented in to be imported using sourceCpp(), however not as an infix function.
My current attempt is as follows:
#include <Rcpp.h>
using namespace Rcpp;
#include <RcppEigen.h>
// [[Rcpp::depends(RcppEigen)]]
// [[Rcpp::export]]
NumericMatrix outerProd(NumericVector v1, NumericVector v2) {
NumericVector xx(v1);
NumericVector yy(v2);
const Eigen::Map<Eigen::VectorXd> x(as<Eigen::Map<Eigen::VectorXd> >(xx));
const Eigen::Map<Eigen::VectorXd> y(as<Eigen::Map<Eigen::VectorXd> >(yy));
Eigen::MatrixXd op = x * y.transpose();
return Rcpp::wrap(op);
}
So to summarize my question.. Is it possible to make an infix function available through sourceCpp?
Is it possible to make an infix function available through sourceCpp?
Yes.
As always, one should read the Rcpp vignettes!
In particular here, if you look in Section 1.6 of the Rcpp attributes vignette, you'd see you can modify the name of a function using the name parameter for Rcpp::export.
For example, we could do:
#include <Rcpp.h>
// [[Rcpp::export(name = `%+%`)]]
Rcpp::NumericVector add(Rcpp::NumericVector x, Rcpp::NumericVector y) {
return x + y;
}
/*** R
1:3 %+% 4:6
*/
Then we'd get:
Rcpp::sourceCpp("~/infix-test.cpp")
> 1:3 %+% 4:6
[1] 5 7 9
So, you still have to name C++ functions valid C++ names in the code, but you can export it to R through the name parameter of Rcpp::export without having to do anything further on the R side.
John Chambers states three principles on page four of the (highly recommended) "Extending R" book:
Everything that exists in R is an object.
Everything that happens in R is a function call.
Interfaces to other software are part of R.
So per point two, you can of course use sourceCpp() to create your a compiled function and hang that at any odd infix operator you like.
Code Example
library(Rcpp)
cppFunction("std::string cc(std::string a, std::string b) { return a+b; }")
`%+%` <- function(a,b) cc(a,b)
cc("Hello", "World")
"hello" %+% "world"
Output
R> library(Rcpp)
R> cppFunction("std::string cc(std::string a, std::string b) { return a+b; }")
R> `%+%` <- function(a,b) cc(a,b)
R>
R> cc("Hello", "World")
[1] "HelloWorld"
R>
R> "hello" %+% "world"
[1] "helloworld"
R>
Summary
Rcpp is really just one cog in the machinery.
Edit
It also works with your initial function, with some minor simplification. For
`%op%` <- cppFunction("Eigen::MatrixXd op(Eigen::VectorXd x, Eigen::VectorXd y) { Eigen::MatrixXd op = x * y.transpose(); return op; }", depends="RcppEigen")
as.numeric(1:3) %op% as.numeric(3:1)
we get
R> `%op%` <- cppFunction("Eigen::MatrixXd op(Eigen::VectorXd x, Eigen::VectorXd y) { Eigen::MatrixXd op = x * y.transpose(); return op; }", depends="RcppEigen")
R> as.numeric(1:3) %op% as.numeric(3:1)
[,1] [,2] [,3]
[1,] 3 2 1
[2,] 6 4 2
[3,] 9 6 3
R>
(modulo some line noise from the compiler).

(Rcpp, armadillo) convert arma::vec to arma::mat

I have a matrix X, which is vectorized by arma::vectorise function. After some computation on the converted vector x, I want to reshape it into arma::mat. I tried to use .reshape function in Armadillo, but it gives me this error.
Rcpp code
// [[Rcpp::export]]
arma::mat vec2mat(arma::vec x, int nrow, int ncol){
return x.reshape(nrow, ncol);
}
Error message
no viable conversion from returned value of type 'void' to function return type 'arma::mat' (aka 'Mat<doubld>')
Would anyone help me to find a good way to handle this? I'm not sure what type I should use for function return type in this case. If you know another way to convert vector to matrix, then it would be also great :)
Thanks in advance!
You overlooked / ignored details in the Armadillo documentation: reshape() is a member function of an already existing matrix whereas you try to force it with an assignment. And the compiler tells you no mas. So listen to the compiler.
Working code
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::mat vec2mat(arma::vec x, int nrow, int ncol) {
arma::mat y(x);
y.reshape(nrow, ncol);
return y;
}
Demo
> Rcpp::sourceCpp("56606499/answer.cpp") ## filename I used
> vec2mat(sqrt(1:10), 2, 5)
[,1] [,2] [,3] [,4] [,5]
[1,] 1.000000 1.732051 2.236068 2.645751 3.000000
[2,] 1.414214 2.000000 2.449490 2.828427 3.162278
>

Using RcppArmadillo each_col with lambda function?

According to the Armadillo website, you can pass in a lambda function into .each_col, such as
X.each_col( [](vec& a){ a.print(); } );
The following Rcpp seems to have an error though, reporting "Expected Expression"
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
using namespace arma;
// [[Rcpp::export]]
arma::vec colCumSum(const arma::mat& X) {
return X.each_col( [](const arma::vec& b){ b.cumsum(); } );
}
You actually have to tell R to use C++11 in order to have lambda support. The magic line is [[Rcpp::plugins("cpp11")]] which makes it all work:
But once I do that I get issues on the cumsum(). You also had too many const in there.
So here is a simpler version which does work with another lambda from the documentation -- which just prints. I also turned to ivec and imat for consistency:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::plugins("cpp11")]]
// [[Rcpp::export]]
arma::ivec colCumSum(arma::imat& X) {
X.each_col( [](arma::ivec& a){ a.print(); } );
return X.col(0);
}
/*** R
M <- matrix(1:16, 4, 4)
colCumSum(M)
*/
When you source this, it builds and runs. You will need to work out the lambda use case for the reduction that cumsum() does.
> sourceCpp("/tmp/foo.cpp")
> M <- matrix(1:16, 4, 4)
> colCumSum(M)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[,1]
[1,] 1
[2,] 2
[3,] 3
[4,] 4
>

Sequence of Integers in Rcpp

I want to create a sequence of integer numbers for indexing within a matrix. The R pendant would be:
indexRow <- max(0,1):min(2,12)
matrix1[indexRow, ]
This is what i have tried in Rcpp to create the sequence of integers:
#include <Rcpp.h>
#include <algorithm>
#include <vector>
#include <numeric>
using namespace Rcpp;
using namespace std;
// [[Rcpp::export]]
NumericVector test(NumericVector x) {
IntegerVector indexRow = Rcpp::seq_along(max(0, 1), min(1, 12));
}
However I get the Error message:
no matching function for call to 'seq_along(const int&, const int&)'
How can I create a sequence of integers in Rcpp?
Here is a possible Rcpp implementation :
library(Rcpp)
cppFunction(plugins='cpp11','NumericVector myseq(int &first, int &last) {
NumericVector y(abs(last - first) + 1);
if (first < last)
std::iota(y.begin(), y.end(), first);
else {
std::iota(y.begin(), y.end(), last);
std::reverse(y.begin(), y.end());
}
return y;
}')
#> myseq(max(0,1), min(13,17))
#[1] 1 2 3 4 5 6 7 8 9 10 11 12 13
This code generates a function myseq which takes two arguments: The first and the last number in an integer series. It is similar to R's seq function called with two integer arguments seq(first, last).
A documentation on the C++11 function std::iota is given here.
seq_along takes in a vector, what you want to use is seq combined with min and max, both take vectors. seq returns an IntegerVector. Here is an example.
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
IntegerVector test(IntegerVector a, IntegerVector b) {
IntegerVector vec = seq(max(a), min(b));
return vec;
}
In R you use
> test(c(0,1), c(2,12))
[1] 1 2

Resources