ヘッダーをスキップ
Oracle® R Enterpriseユーザーズ・ガイド
リリース1.4
E52975-01
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

6 Oracle R Enterpriseの埋込みRの実行の使用方法

埋込みRの実行は、Oracle R Enterpriseの重要な機能です。この章では、埋込みRの実行について、次の各項で説明します。

Oracle R Enterpriseの埋込みRの実行について

Oracle R Enterpriseでは、埋込みRの実行は、RスクリプトをOracle Databaseに格納して起動する機能であり、このスクリプトはその後、データベース内で実行され、データベースによって動的に開始および管理される1つ以上のRエンジンで実行されます。Oracle R Enterpriseでは、埋込みRの実行用にRインタフェースとSQLインタフェースの両方が提供されています。同じRスクリプトから、構造化データ、RオブジェクトおよびイメージのXML表現、さらにはデータベース表のBLOB列を介してPNGイメージを取得できます。

この項の内容は次のとおりです。

埋込みRの実行の利点

埋込みRの実行には次の利点があります。

  • Oracle DatabaseサーバーからローカルのRセッションへデータを移動する必要がありません。

    セキュリティを向上するでなく、Oracle Databaseと内部Rエンジン間のデータベース・データの転送は、別個のクライアントRエンジンよりはるかに高速です。

  • データベース・サーバーを使用して、データベース側RエンジンのRスクリプトの実行を開始、管理および制御します。

  • Rエンジンの実行に、データベース・サーバー・マシンのメモリーおよび処理能力を活用することで、より優れたスケーラビリティおよびパフォーマンスを提供します。

  • Hadoopのマップ/リデュース・ジョブの特殊なケースに対応したユーザー定義のR関数をデータ・パラレルおよびタスク・パラレルに実行できます。

  • パラレル・シミュレーション機能が装備されています。

  • データベース・サーバー・マシンでオープン・ソースのCRANパッケージを使用できます。

  • R環境を終了することなく、分析アプリケーション用の包括的なスクリプトを1つの手順で開発および操作できるようにする機能が装備されています。

    探索的分析で使用されるRスクリプトをアプリケーション・タスクに直接統合できます。また、移植を排除し、アプリケーション・コードに対する変更の即時更新を可能にすることによって、本番でRスクリプトをすばやく起動して、開発期間を大幅に減少できます。

  • SQLからRスクリプトを実行することで、Rスクリプトの結果をOracle Business Intelligence Enterprise Edition (OBIEE)、Oracle BI Publisherおよび構造化データ、Rオブジェクトおよびイメージ用のその他のSQL対応のツールと統合できます。

埋込みRの実行用のAPI

Oracle R Enterpriseには、埋込みRの実行用のRおよびSQLのアプリケーション・プログラミング・インタフェースがあります。表6-1に、埋込みRの実行関数のサマリーおよび使用可能なRスクリプトのリポジトリ関数を示します。関数fは、ユーザー定義のRコード(スクリプト)を参照し、このコードはR関数オブジェクトまたはデータベースのRスクリプト・リポジトリの指定されたR関数のいずれかとして提供されています。

表6-1 埋込みRの実行用のRおよびSQLのAPI

RのAPI SQLのAPI 説明

ore.doEval

rqEval

データを自動転送せずにfを実行します。

ore.tableApply

rqTableEval

fの最初の引数として指定された入力ore.frameのすべての行を渡すことでfを実行します。fの最初の引数をdata.frameとして指定します。

ore.groupApply

rqGroupEval

この関数は、ユーザーが明示的に定義する必要があります。

グループ化列の値に応じてデータをパーティショニングすることでfを実行します。各データ・パーティションをfの最初の引数にdata.frameとして指定します。データベースのサーバー側Rエンジンで各f呼出しのパラレル実行をサポートします。

ore.rowApply

rqRowEval

指定された入力ore.frameの指定された行数(チャンク)を渡すことでfを実行します。各チャンクをfの最初の引数にdata.frameとして指定します。データベースのサーバー側Rエンジンで各f呼出しのパラレル実行をサポートします。

ore.indexApply

該当するものはありません。

データの自動転送なしでfを実行しますが、1からn (nは呼び出す関数の数)の呼出しの索引を指定します。データベースのサーバー側Rエンジンで各f呼出しのパラレル実行をサポートします。

ore.scriptCreate

sys.rqScriptCreate

指定されたR関数をRスクリプト・リポジトリに指定された名前でロードします。

ore.scriptDrop

sys.rqScriptDrop

指定されたR関数をRスクリプト・リポジトリから削除します。


スクリプトのセキュリティに関する考慮事項

RスクリプトおよびSQLスクリプトはどちらもデータベース・サーバーへのアクセスを許可するため、スクリプトの作成を制御する必要があります。RQADMINロールはOracle Database権限の集合で、スクリプトを作成してOracle DatabaseのRスクリプト・リポジトリに格納したり、リポジトリからスクリプトを削除するために、ユーザーが持つ必要のある権限です。

Oracle R EnterpriseをインストールするとRQADMINロールが作成されます。このロールは、明示的にユーザーに付与する必要があります。RQADMINをユーザーに付与するには、SQL*Plusをsysdbaで起動し、次のようなGRANT文(ロールをユーザーRQUSERに付与します)を入力します。

GRANT RQADMIN to RQUSER

注意:

RQADMINは、必要とするユーザーにのみ付与してください。

パラレル実行のサポート

Oracle R Enterpriseの埋込みRの実行関数の一部では、データベースでのパラレル実行の使用がサポートされています。ore.groupApply関数およびore.rowApply関数は、データ・パラレル実行をサポートし、ore.indexApply関数は、タスク・パラレル実行をサポートします。このパラレル実行機能によって、Oracle Exadataデータベース・マシンなどの高パフォーマンスのコンピューティング・ハードウェアをスクリプトで利用できます。

これらの関数のparallel引数には、埋込みRの実行で使用するための並列度を指定します。引数の値には、次のいずれかを指定できます。

  • 特定の並列度では、2以上の正の整数

  • パラレル化しない場合は、FALSEまたは1

  • data引数のデフォルトのパラレル化の場合はTRUE

  • 操作に対するデータベースのデフォルトはNULL

この引数のデフォルト値は、グローバル・オプションore.parallelの値、またはore.parallelが設定されていない場合はFALSEです。

ore.doEvalまたはore.tableApplyを使用して呼び出したユーザー定義のR関数は、並行して実行されません。このような関数は1つのRエンジンで実行されます。

ore.groupApply関数のデータ・パラレル実行では、1つ以上のRエンジンが同じR関数(タスク)をデータの別のパーティションで実行します。この機能によって、たとえば何万または何十万もの予測モデルを顧客に1モデルずつ構築するなどの、多数のモデルの構築が可能です。

ore.rowApply関数のデータ・パラレル実行では、1つ以上のRエンジンが同じR関数をデータの非結合チャンクで実行します。この機能によって、大規模なデータセットでのスケーラブルなモデルのスコアリングおよび予測が可能です。

ore.indexApply関数のタスク・パラレル実行では、1つ以上のRエンジンが同じまたは異なる計算(タスク)を実行します。実行の索引に関連付けられている数字が、関数に提供されます。この機能は、シミュレーションの実行などの各種の操作で重要です。

Oracle Databaseは、複合的である可能性のあるRエンジンの管理および制御をデータベース・サーバーで処理し、自動的にパーティショニングしてデータをRエンジンに渡して並行して実行します。すべてのパーティションですべてのR関数の実行が完了することが保証されますが、そうでない場合はOracle R Enterpriseの関数はエラーを返します。各ユーザー定義の埋込みR関数の実行結果は、ore.listに収集されます。このリストは、ユーザーが結果を要求するまでデータベースに保持されます。

埋込みRの実行では、Comprehensive R Archive Network (CRAN)のオープン・ソースのRパッケージまたは他のサード・パーティのRパッケージの関数を使用する可能性のあるユーザー定義のR関数のデータ・パラレル実行も可能です。ただし、サード・パーティのパッケージは、データベース内並列性を活用しないため、Rの並列性制約の対象となります。サード・パーティのパッケージは、埋込みRの実行でサポートされているデータ・パラレル実行およびタスク・パラレル実行を利用できます。

埋込みRの実行で使用するためのサード・パーティのパッケージのインストール

埋込みRの実行では、Oracle Databaseサーバーで実行されるユーザー定義のR関数で、CRANまたは他のサード・パーティのパッケージを使用できます。埋込みRの実行でサード・パーティのパッケージを使用するには、そのパッケージをデータベース・サーバーにインストールする必要があります。埋込みRの実行用のRインタフェースでこのパッケージを使用する場合は、パッケージをクライアントにもインストールする必要があります。

埋込みRの実行ではCRANパッケージを使用するためにユーザー定義のR関数を使用できますが、オープン・ソースRパッケージはデータベース内並列性を活用しないため、Rの並列性制約の対象となります。CRANパッケージは、埋込みRの実行でサポートされているデータ・パラレル実行およびタスク・パラレル実行を利用できます。

埋込みRの実行では、データベース・サーバー(Oracle Exadataデータベース・マシンなど)上の一般的なRクライアント・マシンよりも多量である可能性の高いメモリーおよびプロセッサ数を利用します。埋込みRの実行では、データベースとRエンジンが同じマシン上にあるため、これらの間でさらに効率的なデータの転送が提供されます。

サード・パーティのパッケージは、Rセッションまたはコマンドラインからインストールできます。Rセッションでのパッケージのインストールの詳細は、「クライアントでのサード・パーティのパッケージの使用方法」を参照してください。

任意のRユーザーおよび埋込みRの実行で使用できるようにパッケージをサーバーにインストールするには、通常、Oracle Database管理者(DBA)がコマンドラインまたは管理ツールからコマンドを実行します。

通常、DBAは次の手順を実行します。

  1. wgetを使用してCRANからパッケージ・ソースをダウンロードします。パッケージが使用していないR Distributionのパッケージに依存している場合は、そのパッケージのソースもダウンロードします。

  2. 次のいずれかを実行します。

    • 単一のOracle Databaseインスタンスでは、ORE CMD INSTALLコマンドを使用してOracle R Enterpriseパッケージと同じ場所($ORACLE_HOME/R/library)にパッケージをインストールします。

    • Oracle Real Application Clusters (Oracle RAC)や複数ノードのOracle Exadataデータベース・マシン環境などの複数のデータベース・サーバーにインストールする場合は、Exadata Distributed Command Line Interface (DCLI)ユーティリティを使用します。単一ノードにパッケージをインストールするには、ORE CMD INSTALLコマンドを使用します。

例6-1に、CRANからarulesパッケージのソースを取得し、LinuxコマンドラインからのORE CMD INSTALLを使用したインストールを示します。

例6-1 単一のデータベースへのパッケージのインストール

wget http://cran.r-project.org/src/contrib/arules_1.1-1.tar.gz
ORE CMD INSTALL arules_1.1-1.tar.gz

例6-2に、arulesパッケージをインストールするためのDLCIコマンドを示します。

例6-2 DCLIを使用したパッケージのインストール

dcli -t -g nodes -l oracle R CMD INSTALL arules_1.1-1.tar.gz

関連項目:


埋込みRの実行用のRインタフェース

Oracle R Enterpriseには、Oracle Databaseに埋め込まれている1つ以上のRエンジンで実行するRスクリプトを起動する関数があります。その他の関数は、データベースのスクリプト・リポジトリに格納されるか、リポジトリからスクリプトを削除するRスクリプトを作成します。この項では、このような関数について説明します。内容は次のとおりです。

スクリプトを実行する関数の引数

Oracle R Enterpriseの埋込みRの実行関数のore.doEvalore.tableApplyore.groupApplyore.rowApplyおよびore.indexApplyには、これらの関数の一部またはすべてに共通の引数があります。一部の関数には、その関数に固有の引数もあります。

この項では、引数について次の各項で説明します。


関連項目:

  • 関数シグネチャおよび関数の引数の詳細は、help(ore.doEval)を呼び出すことで表示されるオンライン・ヘルプを参照してください。

  • 引数の使用例は、「ore.doEval関数の使用方法」および埋込みRの実行関数の使用方法に関するその他の項を参照してください。


実行するための入力関数

すべての埋込みRの実行関数には、スクリプトの実行時に適用するための関数が必要です。次の相互に排他的な引数のどちらかを使用して入力関数を指定します。

  • FUN

  • FUN.NAME

FUN引数は、関数オブジェクトを直接指定された関数としてまたはR変数に割り当てられた関数として使用します。RQADMINロールを持つユーザーのみが、埋込みR関数の呼出し時にFUN引数を使用できます。

FUN.NAME引数には、Rスクリプト・リポジトリに格納されているスクリプトを指定します。格納されたスクリプトには、スクリプトの実行時に適用する関数が含まれます。すべてのOracle R Enterpriseユーザーが、埋込みR関数の呼出し時にFUN.NAME引数を使用できます。

OREmodelsパッケージのOracle R Enterpriseの高度な分析関数であるore.glmore.lmおよびore.neuralは、埋込みRの実行フレームワークを内部で使用し、埋込みRの実行関数では使用できません。

オプションの引数

すべての埋込みRの実行関数は、指定が可能または不可能なオプションの引数も取ります。Oracle R Enterpriseは、ユーザー定義のオプションの引数を入力関数に渡します。モデルなどの複合Rオブジェクトを含む入力関数に、任意の数のオプションの引数を渡すことができます。

ore.で始まる引数は、特殊な制御引数です。Oracle R Enterpriseはそれらを入力関数に渡しませんが、かわりに、それらを使用して入力関数の実行前または後に発生することを制御します。次の制御引数がサポートされます。

  • ore.connectは、埋込みRの実行関数内でOracle R Enterpriseに自動的に接続するかどうかを制御します。これは、クライアント・セッションと同じ資格証明を指定してore.connectをコールすることと同等です。デフォルト値はFALSEです。

  • ore.dropは入力データを制御します。TRUEを指定した場合、1列のdata.frameがベクターに変換されます。デフォルト値はTRUEです。

  • ore.na.omit入力データの欠損値の処理を制御します。TRUEを指定した場合、欠損値を含む行またはベクター要素(ore.drop設定に応じて)が入力データから削除されます。チャンクのすべての行に欠損値がある場合、そのチャンクの入力データは空のdata.frameまたはvectorになります。デフォルト値はFALSEです。

  • ore.graphicsは、グラフィカル・ドライバを起動して画像を検索するかどうかを制御します。デフォルト値はTRUEです。

  • ore.png.*には、ore.graphicsTRUEの場合に、pngグラフィック・ドライバの追加引数を指定します。これらの引数のネーミング規則では、png関数の引数にore.png.接頭辞を追加します。たとえば、ore.png.heightを指定すると、引数heightpng関数に渡されます。設定しない場合は、png関数に標準のデフォルト値が使用されます。

戻り値の構造

すべての埋込みRの実行関数に適用されるもう1つの引数にFUN.VALUEがあります。FUN.VALUE引数がNULLの場合、ore.doEval関数およびore.tableApply関数はore.objectクラス・オブジェクトとしてシリアライズRオブジェクトを返し、ore.groupApplyore.indexApplyおよびore.rowApplyの各関数はore.listオブジェクトを返します。ただし、data.frameまたはore.frameFUN.VALUE引数を指定した場合、この関数は、指定したdata.frameオブジェクトまたはore.frameオブジェクトの構造を持つore.frameを返します。

入力データ

ore.doEval関数およびore.indexApply関数は、データベースから自動的にデータを受け取りません。FUN引数またはFUN.NAME引数で指定された関数を単純に実行します。入力関数で必要なすべてのデータは、その関数内で生成されるか、Oracle Database、その他のデータベースまたはフラット・ファイルなどのデータ・ソースから明示的に取得するかのいずれかです。入力関数は、ore.pull関数またはその他の透過層関数を使用して、ファイルまたは表からデータをロードできます。

ore.tableApplyore.groupApplyおよびore.rowApplyの各関数には、入力データとしてデータベース表が必要です。この表はore.frameで表されます。このデータに、X引数(埋込みRの実行関数の最初の引数)で指定するore.frameを指定します。埋込みRの実行関数は、ore.frameオブジェクトを最初の引数としてユーザー定義の入力関数に渡します。


注意:

ユーザー定義のR関数に渡されたore.frameオブジェクトによって表されるデータは、Oracle Databaseからデータベース・サーバーのRエンジンにコピーされます。Rメモリーの制限が適用されます。データベース・サーバー・マシンに32GBのRAMがあり、データ表が64GBの場合、Oracle R EnterpriseはデータをRエンジンのメモリーにロードできません。

埋込みRの実行関数が渡す、ore.tableApplyを使用して呼び出したユーザー定義のR関数の最初の引数として提供されたore.frameオブジェクトの入力データは、Oracle Databaseからデータベース・サーバーのRエンジンに物理的に移動されます。Rのメモリー制限がここにも適用されることに注意してください。データベース・サーバー・マシンに32GBのRAMがあり、データ表が64GBの場合、Oracle R EnterpriseはデータをRエンジンのメモリーにロードできません。

パラレル実行

ore.groupApplyore.indexApplyおよびore.rowApplyの各関数は、parallel引数を取ります。この引数には、入力関数の埋込みRの実行で使用するための並列度を指定します。「パラレル実行のサポート」を参照してください。

固有の引数

ore.groupApplyore.indexApplyおよびore.rowApplyの各関数は、関数に固有の引数を取ります。

ore.groupApply関数はINDEX引数を取り、これには、入力データの行が入力関数での処理のためにパーティショニングされる列の名前を指定します。

ore.indexApply関数はtimes引数を取り、これには、入力関数を実行する回数を指定します。

ore.rowApply関数はrows引数を取り、これには、入力関数の各呼出しに渡す行の数を指定します。

埋込みRスクリプトでの自動データベース接続

埋込みRスクリプトは、Oracle Databaseに自動的に接続できます。

自動接続を有効にすると、次の機能が実行されます。

  • 埋込みRスクリプトが自動的にデータベースに接続します。

  • 自動接続は、埋込みR SQL関数を起動するセッションと同じ資格証明を持ちます。

  • このスクリプトは自律型トランザクション内で実行されます。

  • ROracle問合せは自動接続と連携します。

  • Oracle R Enterpriseの透過層が埋込みスクリプトで使用可能になります。

  • ユーザーおよびサイト全体でのRプロファイルのロードは埋込みRでは無効になっています。

    プロファイルのロードは、Oracle R Enterpriseの以前のリリースでサポートされていました。自動接続は、より安全な接続を提供します。

自動接続は、デフォルトでは無効になっています。自動接続は、ore.connect制御引数を使用して有効または無効に指定できます。制御引数については、ore.doEvalに関するRオンライン・ヘルプに記載されています。

自動接続を可能にするため、ROracleが拡張されて、新しいドライバExtDriverとコンストラクタExtprocが追加されました。これは、extprocコンテキストをラップする外部ポインタを渡すことで初期化されます。OraDriverと同様に、ExtDriverはシングルトンです。これらのドライバは、2つの個別のシングルトンで表されるため、セッションで同時に存在できます。この設定によって、次の例に示すように、extproc接続と明示的なOraDriver接続を、同じRスクリプトで機能させることができます。

ore.doEval(function() {
  ore.disconnect()
  con1 <- dbConnect(Extproc())
  res1 <- dbGetQuery(con1, "select * from grade order by name")
  con2 <- dbConnect(Oracle(), "scott", "tiger")
  res2 <- dbGetQuery(con2, "select * from emp order by empno")
  dbDisconnect(con1)
  dbDisconnect(con2)
  cbind(head(res1)[,1:3], head(res2)[,1:3])
} }, ore.connect = TRUE)

ore.doEval関数の使用方法

ore.doEval関数は、入力関数によって生成されたデータを使用して指定された入力関数を実行します。ore.frameオブジェクトまたはシリアライズRオブジェクトをore.objectオブジェクトとして返します。

例6-3では、data.frameオブジェクトを返すfunctionオブジェクトのRandomRedDotsを作成し、これには、引数があり、2列で、100個のランダムの標準値があります。この例では次に、ore.doEval関数を呼び出して、RandomRedDotsオブジェクトを渡します。イメージがクライアントに表示されますが、これはRandomRedDots関数を実行したデータベース・サーバーのRエンジンによって生成されます。

例6-3 ore.doEval関数の使用方法

RandomRedDots <- function(divisor=100){
  id<- 1:10
  plot(1:100, rnorm(100), pch = 21, bg = "red", cex = 2 )
  data.frame(id=id, val=id / divisor)
}
ore.doEval(RandomRedDots)

例6-3のリスト

R> RandomRedDots <- function(divisor=100){
+   id<- 1:10
+   plot(1:100, rnorm(100), pch = 21, bg = "red", cex = 2 )
+   data.frame(id=id, val=id / divisor)
+ }
R> ore.doEval(RandomRedDots)
   id  val
1   1 0.01
2   2 0.02
3   3 0.03
4   4 0.04
5   5 0.05
6   6 0.06
7   7 0.07
8   8 0.08
9   9 0.09
10 10 0.10

図6-1 ランダムの赤い点の表示

図6-1の説明が続きます
「図6-1 ランダムの赤い点の表示」の説明

doEval関数のオプションの引数として入力関数に引数を指定できます。例6-4では、RandomRedDots関数のdivisor引数をオーバーライドするオプションの引数を指定してdoEval関数を呼び出します。

例6-4 オプションの引数を指定したore.doEval関数の使用方法

ore.doEval(RandomRedDots, divisor=50)

例6-4のリスト

R> ore.doEval(RandomRedDots, divisor=50)
   id  val
1   1 0.02
2   2 0.04
3   3 0.06
4   4 0.08
5   5 0.10
6   6 0.12
7   7 0.14
8   8 0.16
9   9 0.18
10 10 0.20
# The graph displayed by the plot function is not shown.

入力関数がRスクリプト・リポジトリに格納されている場合は、ore.doEval関数をFUN.NAME引数を指定して呼び出せます。例6-5では、ore.doEval関数を呼び出し、その名前でRスクリプト・リポジトリに追加されたRandomRedDots関数であるmyRandomRedDotsを指定します。結果は変数resに割り当てられます。

RandomRedDots関数の戻り値はdata.frameですが、例6-5では、ore.doEval関数はore.objectオブジェクトを返します。data.frameオブジェクトを取得するために、この例ではore.pullを呼び出して結果をクライアントのRエンジンにプルします。

例6-5 FUN.NAME引数を指定したore.doEval関数の使用方法

res <- ore.doEval(FUN.NAME="myRandomRedDots",divisor=50)
class(res)
res.local <- ore.pull(res)
class(res.local)

例6-5のリスト

R> res <- ore.doEval(FUN.NAME = "myRandomRedDots", divisor = 50)
R> class(res)
[1] "ore.object"
attr(,"package")
[1] "OREembed"
R> res.local <- ore.pull(res)
R> class(res.local)
[1] "data.frame"

doEval関数でore.objectではなくore.frameオブジェクトを返すようにするには、例6-6に示すとおり、引数FUN.VALUEを指定して結果の構造を記述します。

例6-6 FUN.VALUE引数を指定したore.doEval関数の使用方法

res.of <- ore.doEval(FUN.NAME="myRandomRedDots", divisor=50,
                     FUN.VALUE= data.frame(id=1, val=1))
class(res.of)

例6-6のリスト

R> res.of <- ore.doEval(FUN.NAME="myRandomRedDots", divisor=50,
+                        FUN.VALUE= data.frame(id=1, val=1))
R> class(res.of)
[1] "ore.frame"
attr(,"package")
[1] "OREbase"

入力関数内でOracle Databaseへの接続を確立するには、特別なオプションの引数ore.connectTRUEに設定します。接続を確立してOracle R Enterpriseパッケージも自動的にロードするために、関数ore.doEvalを呼び出したユーザーの資格証明が使用されます。この機能は、Oracle R Enterpriseの透過層を明示的に使用するか、Oracle R Enterpriseデータストアに対してオブジェクトを保存およびロードするために役立ちます。

例6-7では、例6-3のようにRandomRedDots関数オブジェクトを作成しますが、今回この関数には、データストアの名前を使用する引数を指定します。この例では、myVar変数を作成して、datastore_1という名前のデータストアに保存します。次に、doEval関数を呼び出し、データストアの名前を渡し、ore.connect引数を指定します。

例6-7 ore.connect引数を指定したdoEval関数の使用方法

RandomRedDots <- function(divisor=100, datastore.name="myDatastore"){
  id <- 1:10
  plot(1:100, rnorm(100), pch = 21, bg = "red", cex = 2 )
  ore.load(datastore.name) # contains numeric variable myVar
  data.frame(id=id, val=id / divisor, num=myVar)
}
myVar <- 5
ore.save(myVar, name = "datastore_1")
ore.doEval(RandomRedDots, datastore.name="datastore_1", ore.connect=TRUE)

例6-7のリスト

R> RandomRedDots <- function(divisor=100, datastore.name="myDatastore"){
+   id <- 1:10
+   plot(1:100, rnorm(100), pch = 21, bg = "red", cex = 2 )
+   ore.load(datastore.name) # contains numeric variable myVar
+   data.frame(id=id, val=id / divisor, num=myVar)
+ }
R> ore.doEval(RandomRedDots, datastore.name="datastore_1", ore.connect=TRUE)
   id  val num
1   1 0.01   5
2   2 0.02   5
3   3 0.03   5
4   4 0.04   5
5   5 0.05   5
6   6 0.06   5
7   7 0.07   5
8   8 0.08   5
9   9 0.09   5
10 10 0.10   5
# The graph displayed by the plot function is not shown.

ore.tableApply関数の使用方法

ore.tableApply関数は、入力データとしてore.frameを指定してRスクリプトを起動します。ore.tableApply関数は、ore.frameを最初の引数としてユーザー定義の入力関数に渡します。ore.tableApply関数は、ore.frameオブジェクトまたはシリアライズRオブジェクトをore.objectオブジェクトとして返します。

例6-8では、ore.tableApply関数を使用してirisデータセットにNaive Bayesモデルを構築します。naiveBayes関数はe1071パッケージにあり、クライアントとデータベース・サーバー・マシンの両方のRエンジンにインストールする必要があります。ore.tableApply関数の最初の引数として、ore.push(iris)の呼出しでは一時データベース表およびその表のプロキシであるore.frameが作成されます。2番目の引数は入力関数で、これには引数datがあります。ore.tableApply関数は、ore.framedat引数として入力関数に渡します。この入力関数は、ore.tableApply関数がore.objectオブジェクトとして返すモデルを作成します。

例6-8 ore.tableApply関数の使用方法

library(e1071)
mod <- ore.tableApply(
  ore.push(iris),
  function(dat) {
    library(e1071)
    dat$Species <- as.factor(dat$Species)
    naiveBayes(Species ~ ., dat)
})
class(mod)
mod

例6-8のリスト

R> mod <- ore.tableApply(
+   ore.push(iris),
+   function(dat) {
+     library(e1071)
+     dat$Species <- as.factor(dat$Species)
+     naiveBayes(Species ~ ., dat)
+ })
R> class(mod)
[1] "ore.object"
attr(,"package")
[1] "OREembed"
R> mod
 
Naive Bayes Classifier for Discrete Predictors
 
Call:
naiveBayes.default(x = X, y = Y, laplace = laplace)
 
A-priori probabilities:
Y
    setosa versicolor  virginica 
 0.3333333  0.3333333  0.3333333 
 
Conditional probabilities:
            Sepal.Length
Y             [,1]      [,2]
  setosa     5.006 0.3524897
  versicolor 5.936 0.5161711
  virginica  6.588 0.6358796
 
            Sepal.Width
Y             [,1]      [,2]
  setosa     3.428 0.3790644
  versicolor 2.770 0.3137983
  virginica  2.974 0.3224966
 
            Petal.Length
Y             [,1]      [,2]
  setosa     1.462 0.1736640
  versicolor 4.260 0.4699110
  virginica  5.552 0.5518947
 
            Petal.Width
Y             [,1]      [,2]
  setosa     0.246 0.1053856
  versicolor 1.326 0.1977527
  virginica  2.026 0.2746501

ore.groupApply関数の使用方法

ore.groupApply関数は、入力データとしてore.frameを指定してRスクリプトを起動します。ore.groupApply関数は、ore.frameを最初の引数としてユーザー定義の入力関数に渡します。ore.groupApply関数のINDEX引数は、ore.frameの列の名前を指定しますが、これによってOracle Databaseはユーザー定義のR関数による処理のために行をパーティショニングします。ore.groupApply関数は、1つ以上のRエンジンが同じR関数(タスク)をデータの別のパーティションで実行するデータ・パラレル実行を使用できます。

ore.groupApply関数は、ore.listオブジェクトまたはore.frameオブジェクトを返します。

ore.groupApply関数の使用例は、次の各項で説明します。

単一列のパーティショニング

例6-9は、C50パッケージを使用して、各状態のデータに1つの流動モデルを作成することを目的に、C5.0ディシジョン・ツリー・モデルをC50churnデータセットに構築します。この例では、次の操作を実行しています。

  • C50パッケージをロードした後に、churnデータセットをロードします。

  • ore.create関数を使用して、データベース表およびchurnTrain (data.frameオブジェクト)からプロキシore.frameオブジェクトを作成します。

  • CHURN_TRAIN (ore.frameオブジェクト)をore.groupApply関数の最初の引数として指定し、state列をINDEX引数として指定します。ore.groupApply関数は、state列のデータをパーティショニングし、ユーザー定義の関数を各パーティションで呼び出します。

  • ユーザー定義の関数を指定します。ユーザー定義の関数の最初の引数は、データ(1つの状態に関連付けられたすべてのデータ)の1つのパーティションを受け取ります。

  • ユーザー定義の関数は、次のことを実行します。

    • データベースのRエンジンで起動したときに関数で使用できるように、C50パッケージをロードします。

    • state列がモデルに含まれないように、data.frameからこの列を削除します。

    • ore.frameはファクタを定義しますが、ユーザー定義の関数にロードされたときにファクタが文字列ベクターとして表示されるため、列をファクタに変換します。

    • 状態のモデルを構築し、それを返します。

  • ore.groupApply関数は、データの各パーティションでユーザー定義の関数を実行した結果を含むリストを返します。この場合は、状態ごとに1つのC5.0モデルです。

  • この例では、変数modListを作成しますが、これはore.groupApplyによって返されるore.listオブジェクトを取得します。ore.listオブジェクトには、データの各パーティションでユーザー定義の関数を実行した結果が含まれています。この場合は、状態ごとに1つのC5.0モデルで、各モデルはore.objectオブジェクトとして格納されています。

  • ore.pull関数を使用してデータベースからmod.MA変数としてモデルを取得し、そこでsummary関数を呼び出します。mod.MAのクラスはC5.0です。

例6-9 ore.groupApply関数の使用方法

library(C50)
data("churn")
 
ore.create(churnTrain, "CHURN_TRAIN")

modList <- ore.groupApply(
  CHURN_TRAIN,
  INDEX=CHURN_TRAIN$state,
    function(dat) {
      library(C50)
      dat$state <- NULL
      dat$churn <- as.factor(dat$churn)
      dat$area_code <- as.factor(dat$area_code)
      dat$international_plan <- as.factor(dat$international_plan)
      dat$voice_mail_plan <- as.factor(dat$voice_mail_plan)
      C5.0(churn ~ ., data = dat, rules = TRUE)
    });
mod.MA <- ore.pull(modList$MA)
summary(mod.MA)

例6-9のリスト

R> library(C50)
R> data(churn)
R> 
R> ore.create(churnTrain, "CHURN_TRAIN")
R>
R> modList <- ore.groupApply(
+   CHURN_TRAIN,
+   INDEX=CHURN_TRAIN$state,
+     function(dat) {
+       library(C50)
+       dat$state <- NULL
+       dat$churn <- as.factor(dat$churn)
+       dat$area_code <- as.factor(dat$area_code)
+       dat$international_plan <- as.factor(dat$international_plan)
+       dat$voice_mail_plan <- as.factor(dat$voice_mail_plan)
+       C5.0(churn ~ ., data = dat, rules = TRUE)
+     });
R> mod.MA <- ore.pull(modList$MA)
R> summary(mod.MA)
 
Call:
C5.0.formula(formula = churn ~ ., data = dat, rules = TRUE)
 
 
C5.0 [Release 2.07 GPL Edition]         Thu Feb 13 15:09:10 2014
-------------------------------
 
Class specified by attribute `outcome'
 
Read 65 cases (19 attributes) from undefined.data
 
Rules:
 
Rule 1: (52/1, lift 1.2)
        international_plan = no
        total_day_charge <= 43.04
        ->  class no  [0.963]
 
Rule 2: (5, lift 5.1)
        total_day_charge > 43.04
        ->  class yes  [0.857]
 
Rule 3: (6/1, lift 4.4)
        area_code in {area_code_408, area_code_415}
        international_plan = yes
        ->  class yes  [0.750]
 
Default class: no
 
 
Evaluation on training data (65 cases):
 
                Rules     
          ----------------
            No      Errors
 
             3    2( 3.1%)   <<
 
 
           (a)   (b)    <-classified as
          ----  ----
            53     1    (a): class no
             1    10    (b): class yes
 
 
        Attribute usage:
 
         89.23% international_plan
         87.69% total_day_charge
          9.23% area_code
 
 
Time: 0.0 secs

複数列のパーティショニング

ore.groupApply関数はINDEX引数に1つの列のみを取りますが、使用する列を連結した新しい列を作成して、この新しい列をINDEX引数に指定できます。

例6-10は、CHURN_TRAINデータセットのデータを使用して、指定したデータのパーティション(voice_mail_plan列およびinternational_plan列)に対するルールを作成するrpartモデルを構築します。この例では、Rのtable関数を使用して各パーティションで予測される行の数を示します。次に、vmp_ip.g1という名前の新しい列を作成するために、必要な2列を一緒にペーストした新しい列を追加します。

この例では次に、ore.scriptDropを呼び出して、Rスクリプト・リポジトリに指定した名前のスクリプトが存在しないことを確認します。その後、ore.scriptCreate関数を使用してmy.rpartFunctionという名前のスクリプトを定義し、それをリポジトリに格納します。格納されたスクリプトでは、Oracle R Enterpriseのデータストア・オブジェクトの命名に使用されるデータ・ソースおよび接頭辞を使用する関数を定義します。my.rpartFunction関数を呼び出すたびに、vmp_ipで特定されるパーティションの1つからデータを取得します。ソース・パーティションの列は定数のため、この関数はそれらをNULLに設定します。文字列ベクターをファクタに変換し、流動を予測するためのモデルを構築し、そこに適切に命名されたデータストアを保存します。この関数は、特定のパーティション列値、流動値の分布およびモデル自身を返すためのリストを作成します。

この例では、次にrpartライブラリをロードし、データストアの接頭辞を設定し、派生列vmp_ipを引数INDEXに対する入力とし、my.rpartFunctionをRスクリプト・リポジトリに格納されているユーザー定義の関数を呼び出すための引数FUN.NAMEの入力として使用して、ore.groupApplyを呼び出します。ore.groupApply関数は、オプションの引数を使用してdatastorePrefix変数をユーザー定義の関数に渡します。この関数は、ユーザー定義の関数の実行時に、オプションの引数ore.connectを使用してデータベースに接続します。ore.groupApply関数は、変数resとしてore.listオブジェクトを返します。

この例では、返されるリストの最初のエントリを表示します。次に、ore.load関数を呼び出して、顧客がボイス・メール・プランと国際プランの両方を持つ場合のモデルをロードします。

例6-10 複数列でデータをパーティションする場合のore.groupApplyの使用方法

library(C50)
data(churn)
ore.drop("CHURN_TRAIN") 
ore.create(churnTrain, "CHURN_TRAIN")
 
table(CHURN_TRAIN$international_plan, CHURN_TRAIN$voice_mail_plan)
CT <- CHURN_TRAIN
CT$vmp_ip <- paste(CT$voice_mail_plan,CT$international_plan,sep="-")
options(width = 80)
head(CT, 3)

ore.scriptDrop("my.rpartFunction")
ore.scriptCreate("my.rpartFunction",
  function(dat,datastorePrefix) {
    library(rpart)
    vmp <- dat[1,"voice_mail_plan"]
    ip <- dat[1,"international_plan"]
    datastoreName <- paste(datastorePrefix,vmp,ip,sep="_")
    dat$voice_mail_plan <- NULL
    dat$international_plan <- NULL
    dat$state <- as.factor(dat$state)
    dat$churn <- as.factor(dat$churn)
    dat$area_code <- as.factor(dat$area_code)
    mod <- rpart(churn ~ ., data = dat)
    ore.save(mod, name=datastoreName, overwrite=TRUE)
    list(voice_mail_plan=vmp,
        international_plan=ip,
        churn.table=table(dat$churn),
        rpart.model = mod)
  })

library(rpart)
datastorePrefix="my.rpartModel"
 
res <- ore.groupApply( CT, INDEX=CT$vmp_ip,
      FUN.NAME="my.rpartFunction",
      datastorePrefix=datastorePrefix,
      ore.connect=TRUE)
res[[1]]
ore.load(name=paste(datastorePrefix,"yes","yes",sep="_"))
mod

例6-10のリスト

R> library(C50)
R> data(churn)
R> ore.drop("CHURN_TRAIN") 
R> ore.create(churnTrain, "CHURN_TRAIN")
R>  
R> table(CHURN_TRAIN$international_plan, CHURN_TRAIN$voice_mail_plan)
     
        no  yes
  no  2180  830
  yes  231   92
R> CT <- CHURN_TRAIN
R> CT$vmp_ip <- paste(CT$voice_mail_plan,CT$international_plan,sep="-")
R> options(width = 80)
R> head(CT, 3)
  state account_length     area_code international_plan voice_mail_plan
1    KS            128 area_code_415                 no             yes
2    OH            107 area_code_415                 no             yes
3    NJ            137 area_code_415                 no              no
  number_vmail_messages total_day_minutes total_day_calls total_day_charge
1                    25             265.1             110            45.07
2                    26             161.6             123            27.47
3                     0             243.4             114            41.38
  total_eve_minutes total_eve_calls total_eve_charge total_night_minutes
1             197.4              99            16.78               244.7
2             195.5             103            16.62               254.4
3             121.2             110            10.30               162.6
  total_night_calls total_night_charge total_intl_minutes total_intl_calls
1                91              11.01               10.0                3
2               103              11.45               13.7                3
3               104               7.32               12.2                5
  total_intl_charge number_customer_service_calls churn vmp_ip
1              2.70                             1    no yes-no
2              3.70                             1    no yes-no
3              3.29                             0    no  no-no
R> 
R> ore.scriptDrop("my.rpartFunction")
R> ore.scriptCreate("my.rpartFunction",
+   function(dat,datastorePrefix) {
+     library(rpart)
+     vmp <- dat[1,"voice_mail_plan"]
+     ip <- dat[1,"international_plan"]
+     datastoreName <- paste(datastorePrefix,vmp,ip,sep="_")
+     dat$voice_mail_plan <- NULL
+     dat$international_plan <- NULL
+     dat$state <- as.factor(dat$state)
+     dat$churn <- as.factor(dat$churn)
+     dat$area_code <- as.factor(dat$area_code)
+     mod <- rpart(churn ~ ., data = dat)
+     ore.save(mod, name=datastoreName, overwrite=TRUE)
+     list(voice_mail_plan=vmp,
+         international_plan=ip,
+         churn.table=table(dat$churn),
+         rpart.model = mod)
+   })
R> 
R> library(rpart)
R> datastorePrefix="my.rpartModel"
R> 
R> res <- ore.groupApply( CT, INDEX=CT$vmp_ip,
+       FUN.NAME="my.rpartFunction",
+       datastorePrefix=datastorePrefix,
+       ore.connect=TRUE)
R> res[[1]]
$voice_mail_plan
[1] "no"
 
$international_plan
[1] "no"
 
$churn.table
 
  no  yes 
1878  302 
 
$rpart.model
n= 2180 
 
node), split, n, loss, yval, (yprob)
      * denotes terminal node
 
 1) root 2180 302 no (0.86146789 0.13853211)  
   2) total_day_minutes< 263.55 2040 192 no (0.90588235 0.09411765)  
     4) number_customer_service_calls< 3.5 1876 108 no (0.94243070 0.05756930)  
       8) total_day_minutes< 223.25 1599  44 no (0.97248280 0.02751720) *
       9) total_day_minutes>=223.25 277  64 no (0.76895307 0.23104693)  
        18) total_eve_minutes< 242.35 210  18 no (0.91428571 0.08571429) *
        19) total_eve_minutes>=242.35 67  21 yes (0.31343284 0.68656716)  
          38) total_night_minutes< 174.2 17   4 no (0.76470588 0.23529412) *
          39) total_night_minutes>=174.2 50   8 yes (0.16000000 0.84000000) *
     5) number_customer_service_calls>=3.5 164  80 yes (0.48780488 0.51219512)  
      10) total_day_minutes>=160.2 95  22 no (0.76842105 0.23157895)  
        20) state=AL,AZ,CA,CO,DC,DE,FL,HI,KS,KY,MA,MD,ME,MI,NC,ND,NE,NH,NM,OK,OR,SC,TN,VA,VT,WY 56   2 no (0.96428571 0.03571429) *
        21) state=AK,AR,CT,GA,IA,ID,MN,MO,NJ,NV,NY,OH,RI,TX,UT,WA,WV 39  19 yes (0.48717949 0.51282051)  
          42) total_day_minutes>=182.3 21   5 no (0.76190476 0.23809524) *
          43) total_day_minutes< 182.3 18   3 yes (0.16666667 0.83333333) *
      11) total_day_minutes< 160.2 69   7 yes (0.10144928 0.89855072) *
   3) total_day_minutes>=263.55 140  30 yes (0.21428571 0.78571429)  
     6) total_eve_minutes< 167.3 29   7 no (0.75862069 0.24137931)  
      12) state=AK,AR,AZ,CO,CT,FL,HI,IN,KS,LA,MD,ND,NM,NY,OH,UT,WA,WV 21   0 no (1.00000000 0.00000000) *
      13) state=IA,MA,MN,PA,SD,TX,WI 8   1 yes (0.12500000 0.87500000) *
     7) total_eve_minutes>=167.3 111   8 yes (0.07207207 0.92792793) *
 
R> ore.load(name=paste(datastorePrefix,"yes","yes",sep="_"))
[1] "mod"
R> mod
n= 92 
 
node), split, n, loss, yval, (yprob)
      * denotes terminal node
 
1) root 92 36 no (0.60869565 0.39130435)  
  2) total_intl_minutes< 13.1 71 15 no (0.78873239 0.21126761)  
    4) total_intl_calls>=2.5 60  4 no (0.93333333 0.06666667)  
      8) state=AK,AR,AZ,CO,CT,DC,DE,FL,GA,HI,ID,IL,IN,KS,MD,MI,MO,MS,MT,NC,ND,NE,NH,NJ,OH,SC,SD,UT,VA,WA,WV,WY 53  0 no (1.00000000 0.00000000) *
      9) state=ME,NM,VT,WI 7  3 yes (0.42857143 0.57142857) *
    5) total_intl_calls< 2.5 11  0 yes (0.00000000 1.00000000) *
  3) total_intl_minutes>=13.1 21  0 yes (0.00000000 1.00000000) *

ore.rowApply関数の使用方法

ore.rowApply関数は、入力データとしてore.frameを指定してRスクリプトを起動します。ore.rowApply関数は、ore.frameを最初の引数としてユーザー定義の入力関数に渡します。ore.rowApply関数に対するrows引数には、ユーザー定義のR関数の呼出しごとに渡す行の数を指定します。最後のチャンクまたは行は、指定した数より少なくなる可能性があります。ore.rowApply関数は、1つ以上のRエンジンが同じR関数(タスク)をデータの別のパーティションで実行するデータ・パラレル実行を使用できます。

ore.rowApply関数は、ore.listオブジェクトまたはore.frameオブジェクトを返します。

例6-11では、事前にCRANからダウンロードしてあるe1071パッケージを使用します。また、この例では、例6-8「ore.tableApply関数の使用方法」で作成したNaive Bayeモデルであるmodオブジェクトも使用します。

例6-11では、次の処理を行います。

  • パッケージe1071をロードします。

  • irisデータセットをIRIS一時表およびore.frameとしてデータベースにプッシュします。

  • IRISIRIS_PREDとしてコピーし、予測を含めるためにPRED列をIRIS_PREDに追加します。

  • ore.rowApply関数を呼び出し、IRISore.frameをユーザー定義のR関数として渡して関数を定義します。

  • ユーザー定義の関数は、次のことを実行します。

    • Rエンジンまたはデータベース内で稼働するエンジンで使用できるように、パッケージe1071をロードします。

    • ore.frameはファクタを定義しますが、ユーザー定義の関数にロードされたときにファクタが文字列ベクターとして表示されるため、Species列をファクタに変換します。

    • predictメソッドを起動し、データセットに追加された列に予測が含まれているresオブジェクトを返します。

  • この例では、モデルをクライアントのRセッションにプルします。

  • IRIS_PREDを引数FUN.VALUEとして渡しますが、この引数にore.rowApply関数が返すオブジェクトの構造を指定します。

  • ユーザー定義関数の呼出しごとに渡す行の数を指定します。

  • resのクラスを表示し、table関数を呼び出してSpecies列およびresオブジェクトのPRED列を表示します。

例6-11 ore.rowApply関数の使用方法

library(e1071)
IRIS <- ore.push(iris)
IRIS_PRED <- IRIS
IRIS_PRED$PRED <- "A"
res <- ore.rowApply(
  IRIS,
  function(dat, mod) {
    library(e1071)
    dat$Species <- as.factor(dat$Species)
    dat$PRED <- predict(mod, newdata = dat)
    dat
  },
  mod = ore.pull(mod),
  FUN.VALUE = IRIS_PRED,
  rows=10)
class(res)
table(res$Species, res$PRED)

例6-11のリスト

R> library(e1071)
R> IRIS <- ore.push(iris)      
R> IRIS_PRED <- IRIS
R> IRIS_PRED$PRED <- "A"
R> res <- ore.rowApply(
+   IRIS ,
+   function(dat, mod) {
+     library(e1071)
+     dat$Species <- as.factor(dat$Species)
+     dat$PRED <- predict(mod, newdata = dat)
+     dat
+   },
+   mod = ore.pull(mod),
+   FUN.VALUE = IRIS_PRED,
+   rows=10)
R> class(res)
[1] "ore.frame"
attr(,"package")
[1] "OREbase"
R> table(res$Species, res$PRED)
            
             setosa versicolor virginica
  setosa         50          0         0
  versicolor      0         47         3
  virginica       0          3        47

ore.indexApply関数の使用方法

ore.indexApply関数は、入力関数によって生成されたデータを使用して指定されたユーザー定義の入力関数を実行します。これは、1つ以上のRエンジンが同じまたは異なる計算(タスク)を実行するタスク・パラレル実行をサポートします。ore.indexApply関数に対するtimes引数には、データベース内で入力関数を実行する回数を指定します。必要なすべてのデータは、入力関数内で明示的に生成またはロードされる必要があります。

ore.indexApply関数は、ore.listオブジェクトまたはore.frameオブジェクトを返します。

ore.indexApply関数の使用例は、次の各項で説明します。

ore.indexApply関数の簡単な使用例

例6-12では、ore.indexApplyを呼び出し、入力関数を並行して5回実行することを指定します。結果のクラスであるore.listを表示した後に、結果を表示します。

例6-12 ore.indexApply関数の使用方法

res <- ore.indexApply(5,
      function(index) {
        paste("IndexApply:",index)
      },
      parallel=TRUE)
class(res)
res
R> res <- ore.indexApply(5,
+       function(index) {
+         paste("IndexApply:",index)
+       },
+       parallel=TRUE)
R> class(res)
[1] "ore.list"
attr(,"package")
[1] "OREembed"
R> res
$`1`
[1] "IndexApply: 1"
 
$`2`
[1] "IndexApply: 2"
 
$`3`
[1] "IndexApply: 3"
 
$`4`
[1] "IndexApply: 4"
 
$`5`
[1] "IndexApply: 5"

列並行の使用例

例6-12では、Rのsummary関数を使用して、irisデータセットの最初の4つの数値列でサマリー統計を並行して計算します。この例では、計算を最終結果に結合します。ore.indexApply関数の最初の引数は4で、これは、並行してまとめる列の数を指定します。ユーザー定義の入力関数は1つの引数indexを取り、これは、まとめる列を指定する1から4の値です。

この例では、summary関数を指定した列で呼び出します。summaryの呼出しでは、列のサマリー統計が含まれている単一の行が返されます。この例では、summary呼出しの結果をdata.frameに変換し、そこに列名を追加します。

次に、ore.indexApply関数に対してFUN.VALUE引数を使用して、関数の結果の構造を定義します。結果はその後、その構造とともにore.frameオブジェクトとして返されます。

例6-13 ore.indexApply関数の使用方法および結果の結合

res <- NULL
res <- ore.indexApply(4,
      function(index) {
        ss <- summary(iris[, index])
        attr.names <- attr(ss, "names")
        stats <- data.frame(matrix(ss, 1, length(ss)))
        names(stats) <- attr.names
        stats$col <- names(iris)[index]
        stats
      },
      FUN.VALUE=data.frame(Min.=numeric(0),
        "1st Qu."=numeric(0),
        Median=numeric(0),
        Mean=numeric(0),
        "3rd Qu."=numeric(0),
        Max.=numeric(0),
        col=character(0)), 
      parallel=TRUE)
res

例6-13のリスト

R> res <- NULL
R> res <- ore.indexApply(4,
+       function(index) {
+         ss <- summary(iris[,index])
+         attr.names <- attr(ss,"names")
+         stats <- data.frame(matrix(ss,1,length(ss)))
+         names(stats) <- attr.names
+         stats$col <- names(iris)[index]
+         stats
+       },
+       FUN.VALUE=data.frame(Min.=numeric(0),
+         "1st Qu."=numeric(0),
+         Median=numeric(0),
+         Mean=numeric(0),
+         "3rd Qu."=numeric(0),
+         Max.=numeric(0),
+         col=character(0)),
+       parallel=TRUE)
R> res
  Min. X1st.Qu. Median  Mean X3rd.Qu. Max.          col
1  2.0      2.8   3.00 3.057      3.3  4.4  Sepal.Width
2  4.3      5.1   5.80 5.843      6.4  7.9 Sepal.Length
3  0.1      0.3   1.30 1.199      1.8  2.5  Petal.Width
4  1.0      1.6   4.35 3.758      5.1  6.9 Petal.Length
Warning message:
ORE object has no unique key - using random order

シミュレーションの使用例

ore.indexApply関数をシミュレーションで使用しすることで、Oracle Exadataデータベース・マシンなどの高パフォーマンスのコンピューティング・ハードウェアを利用できます。例6-14は、ランダムな正規分布の複数のサンプルを使用してサマリー統計の分布を比較します。各シミュレーションは、データベースの別個のRエンジンで、データベースで許可された並列度まで並列に実行されます。

例6-14では、サンプル・サイズの変数、乱数値の平均および標準偏差および実行するシミュレーションの数を定義します。この例では、num.simulationsore.indexApply関数の最初の引数として指定します。ore.indexApply関数は、num.simulationsindex引数としてユーザー定義の関数に渡します。この入力関数はその後、各入力関数の呼出しで異なる乱数値のセットが生成されるように、索引に基づいて乱数シードを設定します。

次に、入力関数は、rnorm関数を使用してsample.sizeランダムな標準値を生成します。乱数のベクターでsummary関数を呼び出し、返される結果としてdata.frameを準備します。ore.indexApply関数には、シミュレーションの結合された結果を構成するore.frameを返すように、FUN.VALUE引数を指定します。res変数は、ore.indexApply関数によって返されるore.frameを取得します。

サンプルの分布を取得するために、この例では、ore.pull関数を使用した結果であるdata.frameboxplot関数を呼び出し、resから選択した列をクライアントに渡します。

例6-14 シミュレーションでのore.indexApply関数の使用方法

res <- NULL
sample.size = 1000
mean.val = 100
std.dev.val = 10
num.simulations = 1000
 
res <- ore.indexApply(num.simulations,
      function(index, sample.size=1000, mean=0, std.dev=1) {
        set.seed(index)
        x <- rnorm(sample.size, mean, std.dev)
        ss <- summary(x)
        attr.names <- attr(ss,"names")
        stats <- data.frame(matrix(ss,1,length(ss)))
        names(stats) <- attr.names
        stats$index <- index
        stats
      },
      FUN.VALUE=data.frame(Min.=numeric(0),
        "1st Qu."=numeric(0),
        Median=numeric(0),
        Mean=numeric(0),
        "3rd Qu."=numeric(0),
        Max.=numeric(0),
        index=numeric(0)),
      parallel=TRUE,
      sample.size=sample.size,
      mean=mean.val, std.dev=std.dev.val)
options("ore.warn.order" = FALSE)
head(res, 3)
tail(res, 3)
boxplot(ore.pull(res[,1:6]),
  main=sprintf("Boxplot of %d rnorm samples size %d, mean=%d, sd=%d",
               num.simulations, sample.size, mean.val, std.dev.val))

例6-14のリスト

R> res <- ore.indexApply(num.simulations,
+       function(index, sample.size=1000, mean=0, std.dev=1) {
+         set.seed(index)
+         x <- rnorm(sample.size, mean, std.dev)
+         ss <- summary(x)
+         attr.names <- attr(ss,"names")
+         stats <- data.frame(matrix(ss,1,length(ss)))
+         names(stats) <- attr.names
+         stats$index <- index
+         stats
+       },
+       FUN.VALUE=data.frame(Min.=numeric(0),
+         "1st Qu."=numeric(0),
+         Median=numeric(0),
+         Mean=numeric(0),
+         "3rd Qu."=numeric(0),
+         Max.=numeric(0),
+         index=numeric(0)),
+       parallel=TRUE,
+       sample.size=sample.size,
+       mean=mean.val, std.dev=std.dev.val)
R> options("ore.warn.order" = FALSE)
R> head(res, 3)
   Min. X1st.Qu. Median   Mean X3rd.Qu.  Max. index
1 67.56    93.11  99.42  99.30    105.8 128.0   847
2 67.73    94.19  99.86 100.10    106.3 130.7   258
3 65.58    93.15  99.78  99.82    106.2 134.3   264
R> tail(res, 3)
   Min. X1st.Qu. Median   Mean X3rd.Qu.  Max. index
1 65.02    93.44  100.2 100.20    106.9 134.0     5
2 71.60    93.34   99.6  99.66    106.4 131.7     4
3 69.44    93.15  100.3 100.10    106.8 135.2     3
R> boxplot(ore.pull(res[,1:6]),
+   main=sprintf("Boxplot of %d rnorm samples size %d, mean=%d, sd=%d",
+                num.simulations, sample.size, mean.val, std.dev.val))

ore.scriptCreate関数およびore.scriptDrop関数の使用方法

ore.scriptCreate関数は、Oracle DatabaseのRスクリプト・リポジトリにスクリプトを作成します。埋込みRの実行関数は、FUN.NAME引数とともに指定することでこのリポジトリのスクリプトを使用できます。Rスクリプト・リポジトリのスクリプトは、Oracle R Enterpriseの埋込みRの実行用のSQLインタフェースを介しても使用できます。

ore.scriptDrop関数は、指定したRスクリプトをRスクリプト・リポジトリから削除します。


注意:

ore.scriptCreate関数またはore.scriptDrop関数を呼び出すには、RQADMINロールが必要です。

ore.scriptCreateおよびore.scriptDropの両方の関数は、成功した場合は非表示のNULLを返し、スクリプトの作成または削除が成功しなかった場合はエラーを返します。

例6-15では、スクリプトを作成し、それをRスクリプト・リポジトリに格納します。スクリプトのユーザー定義の関数は線形モデルを作成します。この例では、irisデータセットをデータベースにプッシュします。その後、ore.tableApply関数を呼び出し、この格納されたスクリプトにFUN.NAME引数を指定します。例では次に、リポジトリからスクリプトを削除します。

例6-15 ore.scriptCreate関数およびore.scriptDrop関数の使用方法

ore.scriptCreate("MYLM",function(data, formula, ...) lm(formula, data, ...))
IRIS <- ore.push(iris)
ore.tableApply(IRIS[1:4], FUN.NAME = "MYLM", formula = Sepal.Length ~ .)
ore.scriptDrop("MYLM")

例6-15のリスト

R> ore.scriptCreate("MYLM",function(data, formula, ...) lm(formula, data, ...))
R> IRIS <- ore.push(iris)
R> ore.tableApply(IRIS[1:4], FUN.NAME = "MYLM", formula = Sepal.Length ~ .)
 
Call:
lm(formula = formula, data = data)
 
Coefficients:
 (Intercept)   Sepal.Width  Petal.Length   Petal.Width  
      1.8560        0.6508        0.7091       -0.5565
R> ore.scriptDrop("MYLM")

関連項目:

例6-10

埋込みRの実行用のSQLインタフェース

Oracle R Enterpriseの埋込みRの実行用のSQLインタフェースでは、本番データベースのアプリケーションでRスクリプトを実行できます。

SQLインタフェースで使用する関数は、データベースRリポジトリに格納し、SQLのAPI関数の名前で参照する必要があります。リポジトリにスクリプトを追加する方法、リポジトリからスクリプトを削除する方法、およびリポジトリ内のスクリプトの一覧を表示して使用する方法については、「SQLスクリプトの登録および管理」を参照してください。

SQL関数についての説明は、「Oracle R EnterpriseのSQL関数について」を参照してください。

この項では、SQLインタフェースについて、次の各項で説明します。

SQLスクリプトの登録および管理

埋込みRの実行用のSQLインタフェースで使用するR関数は、データベースのRスクリプト・リポジトリに格納し、SQLのAPI関数の名前で参照する必要があります。セキュリティ上の理由により、最初にシステムで一意の名前でRスクリプトを登録し、SQLインタフェース表関数へのコールで実際のスクリプトのかわりに新しい名前を使用する必要があります。

管理用の関数sys.rqScriptCreateおよびsys.rqScriptDropは、スクリプトを作成および削除します。sys.rq_scriptsビューによって、作成したスクリプトをリストおよび使用できます。

スクリプトの作成または削除には、「スクリプトのセキュリティに関する考慮事項」で説明するRQADMINロールが必要です。

sys.rqScriptCreateを使用する場合は、関数文字列の対応するR閉包を指定する必要があります。

例6-16に、Rスクリプトの登録および使用を示します。

例6-16 Rスクリプトの登録および使用方法

begin
  sys.rqScriptCreate('tmrqfun2',
    'function() {
       ID <- 1:10
       res <- data.frame(ID = ID, RES = ID / 100)
       res
  }');
end;
/
 
select *
  from table(rqEval(
        NULL,
       'select 1 id, 1 res from dual',
       'tmrqfun2'));
 
begin
  sys.rqScriptDrop('tmrqfun2');
end;
/

Oracle R EnterpriseのSQL関数について

Oracle R EnterpriseのSQL関数を呼び出すと、データベースの並列性設定に基づいて、1つ以上のRエンジンがデータベースで起動されます。データベースでのRスクリプトの実行を有効化するために、Oracle R Enterpriseでは、ore.doEvalore.tableApplyore.groupApplyおよびore.rowApplyの各関数のSQLバリアントを提供しています。これらのR関数については、「埋込みRの実行用のRインタフェース」で説明しています。

埋込みRの実行用のSQL関数は次のとおりです。

  • rqTableEval

  • rqEval

  • rqRowEval

  • rqGroupEval

rqGroupEval関数には追加のSQL指定が必要で、ここでは、指定された列の値に従ってデータをパーティショニングし、各パーティションでRスクリプトを起動する仮想関数として提供されます。詳細は、「rqGroupEval関数の使用方法」を参照してください。

また、「SQLでのデータストア管理」で説明するように、これらの関数をデータストア内のオブジェクトとともに使用できます。

rqEvalrqTableEvalrqGroupEvalおよびrqRowEvalの各関数は、次のような類似した構文を使用します。

rq*Eval(
     cursor(select * from table-1),
     cursor(select * from table-2),
     'select <column list> from table-3 t',
     <grouping col-name from table-1 or num_rows>,
     <R closure name of registered-R-code>
     )

SQL関数のコンポーネントは次のとおりです。

  • 最初のカーソルは入力カーソルで、入力は、4番目の引数に記述されているR閉包に、表全体、グループまたはN行として一度に渡されます。

    rqEval関数には、このカーソルの引数はありません

  • 2番目のカーソルはパラメータ・カーソルです。1行のスカラー値(文字列、数値またはその両方)を渡すことができます。たとえば、モデルの名前と、モデル設定のいくつかの数値のスカラー値を渡すことができます。

  • 問合せによって、出力表の定義が指定されます。出力は「SELECT文」、「XML」または「PNG」にすることができます。

  • grouping col-namerqGroupEvalに適用され、グループ化列の名前を指定します。

  • num_rowsrqRowEvalに適用され、関数に一度に渡す行の数を指定します。

  • <R closure name of registered-R-code>は、実行するR関数の登録済バージョンです。詳細は、「SQLスクリプトの登録および管理」を参照してください。

すべてのSQL関数の戻り値は、次のいずれかの値を示します。

  • SELECT文に指定された表のシグネチャ。rq関数からの結果を表として返します。

  • XML: 1つのXML文字列で構造化イメージとグラフ・イメージの両方を含むCLOBとして返します。最初に構造化されたコンポーネントが提供され、次にbase 64でエンコードされたイメージのpng表示が続きます。

  • PNG: png形式でグラフ・イメージを含むBLOBとして返します。

rqEvalrqTableEvalrqGroupEvalおよびrqRowEvalの各関数には、Rスクリプト・リポジトリ内に格納された名前でRスクリプトを指定する必要があります。sys.rq_scriptsビューでは、登録されたスクリプトのリストが提供されます。

次の例は、これらの関数の使用方法を示しています。

  • この例では、表fishのすべての行を、他の引数を取らず、すべての入力データおよび値のROWSUMを含むoutputを生成するR関数への入力として使用します。

    このR関数のparam引数はオプションであることに注意してください。

    begin
    sys.rqScriptCreate('tmrqfun2',
    'function(x, param) {
            dat <- data.frame(x, stringsAsFactors=F)
            cbind(dat, ROWSUM = apply(dat,1,sum)+10)
    }');
    end;
    /
     
    select * from table(rqTableEval(  
       cursor(select * from fish),
       NULL,
       'select t.*, 1 rowsum from fish t',
       'tmrqfun2' ));
     
    begin
    sys.rqScriptDrop('tmrqfun2');
    end;
    /
    
  • この例は、表fishからR関数に、一度にn=1(4番目のパラメータ)行を渡す方法を示しています。この関数にパラメータは必要ありません。この関数はROWSUMを生成して、出力のfishに別の列として追加します。

    begin
    sys.rqScriptCreate('tmrqfun2',
    'function(x, param) {
            dat <- data.frame(x, stringsAsFactors=F)
            cbind(dat, ROWSUM = apply(dat,1,sum)+10)
    }');
    end;
    /
     
    select * from table(rqRowEval(  
       cursor(select * from fish),
       NULL,
       'select t.*, 1 rowsum from fish t',
        1,
       'tmrqfun2' ));
     
    begin
    sys.rqScriptDrop('tmrqfun2');
    end;
    /
    

rqGroupEval関数の使用方法

rqGroupEval関数は、グループ化列によってパーティショニングされたデータ上でRスクリプトを呼び出します。rqGroupEval関数では、次のように、2つのPL/SQLオブジェクトを作成する必要があります。

  • 返される結果の型を指定するPL/SQLパッケージ。

  • パッケージの戻り値を取り、その戻り値とPIPELINED_PARALLEL_ENABLEセットを使用してデータをパーティショニングする列を示す関数。

ONTIME_Sは、飛行機の到着についての情報を格納した表であるとします。このデータ・カーソルはすべてのデータを使用しますが、PL/SQLレコードを使用して一部の列を使用するカーソルを定義することもできます。次に、特定のデータ・カーソルに対して使用する必要のあるグループ化列と同じ数のPL/SQL表関数を定義する必要があります。

CREATE PACKAGE ontimePkg AS
  TYPE cur IS REF CURSOR RETURN ontime_s%ROWTYPE;
END ontimePkg;
/
 
CREATE FUNCTION ontimeGroupEval(
  inp_cur  ontimePkg.cur,
  par_cur  SYS_REFCURSOR,
  out_qry  VARCHAR2,
  grp_col  VARCHAR2,
  exp_txt  CLOB)
RETURN SYS.AnyDataSet
PIPELINED PARALLEL_ENABLE (PARTITION inp_cur BY HASH (month))
CLUSTER inp_cur BY (month)
USING rqGroupEvalImpl;
/

この時点では、1つのグループ化列のみがサポートされています。複数の列がある場合、それらの列を1つの列に結合して、その新しい列をグループ化列として使用します。PARALLEL_ENABLE句はオプションですが、CLUSTER BY句はオプションではありません。

データストアでのSQL関数およびオブジェクトの使用方法

埋込みRの実行用のSQL関数では、データストアに保存したシリアライズRオブジェクトをパラメータ・カーソルで使用できます。シリアライズRオブジェクトのオブジェクト名およびデータストア名を、パラメータ・カーソル内のR関数のパラメータ名に関連付けます。

例6-17に、rqTableEval関数の使用方法およびカーソルでのデータストアの指定方法を示します。この例では、ontime_modelという名前のデータストアを使用して、このデータストアからlm.modモデル・オブジェクトを取得します。例では、埋込みRの実行を使用して、スコアリング用にSQLでモデルを使用します。

例6-17 rqTableEvalの使用方法およびデータストアの指定

begin
  sys.rqScriptCreate('tmrqmodelscore',
    'function(dat, in.dsname, in.objname) {
       ore.load(name=in.dsname, list=in.objname)
       mod <- get(in.objname)
       prd <- predict(mod, newdata=dat)
       prd[as.integer(rownames(prd))] <- prd
       res <- cbind(dat, PRED = prd)
       res
    }');
end;
/ -- score model
 
select * from table(rqTableEval(
             cursor(select ARRDELAY, DISTANCE, DEPDELAY from ontime_s
                where year = 2003 and month = 5 and dayofmonth = 2),
             cursor(select 'ontime_model' as "in.dsname", 
            'lm.mod' as "in.objname", 1 as "ore.connect" from dual),
             'select ARRDELAY, DISTANCE, DEPDELAY, 1 PRED from ontime_s',
            'tmrqmodelscore'))
order by 1, 2, 3;

SQLでのデータストア管理

Oracle R Enterpriseは、SQLでの基本的なデータストア管理機能を提供します。基本的なデータストア管理には、表示、検索および削除があります。次の関数およびビューを提供します。

  • rqDropDataStoreは、データストアおよびデータストア内のすべてのオブジェクトを削除します。

    構文: rqDropDataStore('<ds_name>')。ここで、<ds_name>は削除するデータストアの名前です。

    次の例では、現行のユーザーのスキーマからデータストアds_modelを削除します。

    rqDropDataStore('ds_model')
    
  • rquser_DataStoreListは、現行のユーザーのスキーマにあるすべてのデータストアの、データストアレベルの情報が含まれるビューです。この情報は、データストア名、オブジェクト数、サイズ、作成日および説明で構成されます。

    次の例は、このビューの使用方法を示しています。

    select * from rquser_DataStoreList;
    select dsname, nobj, dssize from rquser_datastorelist where dsname = 'ds_1';
    
  • rquser_DataStoreContentsは、現行のユーザーのスキーマにあるすべてのデータストアの、オブジェクトレベルの情報が含まれるビューです。この情報は、オブジェクト名、サイズ、クラス、長さ、行および列の数で構成されます。

    この例は、データストアds_1の内容をリストします。

    select * from rquser_DataStoreContents where dsname = 'ds_1';