R で Rcpp を使いパッケージを作成してみる (Rcpp パッケージを使用)
Rcpp パッケージは R と C++ を統合する機能をもった R の関数と C++ ライブラリです.
このWebページでは、 次のことを行う.
- 次のパッケージをインストール
- 自前のパッケージを作成し,読み込んでみる.
- C++ の関数へのデータの受け渡し
【関連する外部ページ】 http://cran.r-project.org/web/packages/Rcpp/index.html
インストール
R で Rcpp パッケージのインストール
- R の起動
- install.packages("Rcpp") と install.packages("RcppExamples") の実行
install.packages("Rcpp") install.packages("RcppExamples")
- ミラーサイトの選択
- library(Rcpp) と library(RcppExamples) の実行
library(Rcpp) library(RcppExamples)
- vignette("Rcpp-package") の実行
使ってみる
- R の起動
cd /tmp R
- Rcpp パッケージの読み込み
library(Rcpp)
- Rcpp.package.skeleton("hoge" )
- 端末を開く
- 端末で「R CMD INSTALL hoge」を実行する
cd /tmp R CMD INSTALL hoge
- R で「rcpp_hello_world()」を実行する
library(Rcpp) library(hoge) rcpp_hello_world()
C++ の関数へのデータの受け渡し
整数、浮動小数点数、文字列
先ほど作成した hoge/src/rcpp_hello_world.cpp を次のように編集
#include "rcpp_hello_world.h"
SEXP foo(SEXP _n, SEXP _d, SEXP _s) {
int n = Rcpp::as(_n);
double d = Rcpp::as(_d);
std::string s = Rcpp::as(_s);
fprintf(stderr, "n = %d\n", n);
fprintf(stderr, "d = %f\n", d);
fprintf(stderr, "s = %s\n", s.data());
return Rcpp::List::create(n);
}
先ほど作成した hoge/src/rcpp_hello_world.h を次のように編集
#ifndef _hoge_RCPP_HELLO_WORLD_H
#define _hoge_RCPP_HELLO_WORLD_H
#include<Rcpp.h>
RcppExport
SEXP foo(SEXP _n, SEXP _d, SEXP _s);
#endif
端末で次のように操作
R CMD INSTALL hoge
R で次のように操作
library(Rcpp)
library(hoge)
foo <- function(n, x, s) { .Call("foo", n, x, s, PACKAGE="hoge") }
foo( 10, 3.14, "red" )

ベクトル
先ほど作成した hoge/src/rcpp_hello_world.cpp を次のように編集
#include "rcpp_hello_world.h"
SEXP foo(SEXP _v, SEXP _iv, SEXP _cv) {
Rcpp::NumericVector v(_v);
Rcpp::IntegerVector iv(_iv);
Rcpp::CharacterVector cv(_cv);
fprintf(stderr, "v(0) = %f\n", v(0));
fprintf(stderr, "v(1) = %f\n", v(1));
fprintf(stderr, "v(2) = %f\n", v(2));
fprintf(stderr, "iv(0) = %d\n", iv(0));
fprintf(stderr, "iv(1) = %d\n", iv(1));
fprintf(stderr, "iv(2) = %d\n", iv(2));
fprintf(stderr, "cv(0) = %s\n", (char*)cv(0));
fprintf(stderr, "cv(1) = %s\n", (char*)cv(1));
fprintf(stderr, "cv(2) = %s\n", (char*)cv(2));
v(0) = v(0) * 100;
v(1) = v(1) * 100;
v(2) = v(2) * 100;
iv(0) = iv(0) + 500;
iv(1) = iv(1) + 500;
iv(2) = iv(2) + 500;
return Rcpp::List::create(v, iv, cv);
}
先ほど作成した hoge/src/rcpp_hello_world.h を次のように編集
#ifndef _hoge_RCPP_HELLO_WORLD_H
#define _hoge_RCPP_HELLO_WORLD_H
#include<Rcpp.h>
RcppExport
SEXP foo(SEXP _v, SEXP _iv, SEXP _cv);
#endif
端末で次のように操作
R CMD INSTALL hoge
R で次のように操作
library(Rcpp)
library(hoge)
foo <- function(v, iv, cv) { .Call("foo", v, iv, cv, PACKAGE="hoge") }
v <- c(1, 2, 3)
iv <- c(4, 5, 6)
cv <- c("red", "white", "blue")
foo( v, iv, cv )
行列
先ほど作成した hoge/src/rcpp_hello_world.cpp を次のように編集
#include "rcpp_hello_world.h"
SEXP foo(SEXP _v, SEXP _iv, SEXP _cv) {
Rcpp::NumericMatrix v(_v);
Rcpp::IntegerMatrix iv(_iv);
Rcpp::CharacterMatrix cv(_cv);
fprintf(stderr, "v(0,0) = %f\n", v(0,0));
fprintf(stderr, "v(1,0) = %f\n", v(1,0));
fprintf(stderr, "v(0,1) = %f\n", v(0,1));
fprintf(stderr, "v(1,1) = %f\n", v(1,1));
fprintf(stderr, "iv(0,0) = %d\n", iv(0,0));
fprintf(stderr, "iv(1,0) = %d\n", iv(1,0));
fprintf(stderr, "iv(0,1) = %d\n", iv(0,1));
fprintf(stderr, "iv(1,1) = %d\n", iv(1,1));
fprintf(stderr, "cv(0,0) = %s\n", (char *)cv(0,0));
fprintf(stderr, "cv(1,0) = %s\n", (char *)cv(1,0));
fprintf(stderr, "cv(0,1) = %s\n", (char *)cv(0,1));
fprintf(stderr, "cv(1,1) = %s\n", (char *)cv(1,1));
return Rcpp::List::create(v, iv, cv);
}
先ほど作成した hoge/src/rcpp_hello_world.h を次のように編集
#ifndef _hoge_RCPP_HELLO_WORLD_H
#define _hoge_RCPP_HELLO_WORLD_H
#include<Rcpp.h>
RcppExport
SEXP foo(SEXP _v, SEXP _iv, SEXP _cv);
#endif
端末で次のように操作
R CMD INSTALL hoge
R で次のように操作
library(Rcpp)
library(hoge)
foo <- function(m, im, cm) { .Call("foo", m, im, cm, PACKAGE="hoge") }
m <- matrix( c(1, 2, 3, 4, 5, 6), ncol=2 )
im <- matrix( c(10, 20, 30, 40, 50, 60), ncol=2 )
cm <- matrix( c("red", "green", "blue", "black", "white", "orange"), ncol=2 )
foo( m, im, cm )
