金子邦彦研究室プログラミングR のプログラム例R で Rcpp を使いパッケージを作成してみる (Rcpp パッケージを使用)

R で Rcpp を使いパッケージを作成してみる (Rcpp パッケージを使用)

Rcpp パッケージは R と C++ を統合する機能をもった R の関数と C++ ライブラリです.

このWebページでは、 次のことを行う.

関連する外部ページhttp://cran.r-project.org/web/packages/Rcpp/index.html

インストール

R で Rcpp パッケージのインストール

  1. R の起動

    [image]
  2. install.packages("Rcpp")
    install.packages("RcppExamples")
    
  3. ミラーサイトの選択
  4. library(Rcpp) と library(RcppExamples) の実行
    library(Rcpp)
    library(RcppExamples)
    
  5. vignette("Rcpp-package") の実行

    [image]

使ってみる

  1. R の起動
    cd /tmp
    R
    
  2. Rcpp パッケージの読み込み
    library(Rcpp)
    
  3. Rcpp.package.skeleton("hoge" )
  4. 端末を開く
  5. 端末で「R CMD INSTALL hoge」を実行する
    cd /tmp
    R CMD INSTALL hoge
    
  6. 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" )

[image]

ベクトル

先ほど作成した 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 )

[image]