埋込み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の実行には次の利点があります。
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対応のツールと統合できます。
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 | 説明 |
---|---|---|
|
|
データを自動転送せずにfを実行します。 |
|
|
fの最初の引数として指定された入力 |
|
rqGroupEval この関数は、ユーザーが明示的に定義する必要があります。 |
グループ化列の値に応じてデータをパーティショニングすることでfを実行します。各データ・パーティションをfの最初の引数に |
|
|
指定された入力 |
|
該当するものはありません。 |
データの自動転送なしでfを実行しますが、1からn (nは呼び出す関数の数)の呼出しの索引を指定します。データベースのサーバー側Rエンジンで各f呼出しのパラレル実行をサポートします。 |
|
|
指定されたR関数をRスクリプト・リポジトリに指定された名前でロードします。 |
|
|
指定された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の実行では、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は次の手順を実行します。
wget
を使用してCRANからパッケージ・ソースをダウンロードします。パッケージが使用していないR Distributionのパッケージに依存している場合は、そのパッケージのソースもダウンロードします。
次のいずれかを実行します。
単一の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コマンドを示します。
関連項目:
|
Oracle R Enterpriseには、Oracle Databaseに埋め込まれている1つ以上のRエンジンで実行するRスクリプトを起動する関数があります。その他の関数は、データベースのスクリプト・リポジトリに格納されるか、リポジトリからスクリプトを削除するRスクリプトを作成します。この項では、このような関数について説明します。内容は次のとおりです。
Oracle R Enterpriseの埋込みRの実行関数のore.doEval
、ore.tableApply
、ore.groupApply
、ore.rowApply
およびore.indexApply
には、これらの関数の一部またはすべてに共通の引数があります。一部の関数には、その関数に固有の引数もあります。
この項では、引数について次の各項で説明します。
関連項目:
|
すべての埋込みRの実行関数には、スクリプトの実行時に適用するための関数が必要です。次の相互に排他的な引数のどちらかを使用して入力関数を指定します。
FUN
FUN.NAME
FUN
引数は、関数オブジェクトを直接指定された関数としてまたはR変数に割り当てられた関数として使用します。RQADMINロールを持つユーザーのみが、埋込みR関数の呼出し時にFUN
引数を使用できます。
FUN.NAME
引数には、Rスクリプト・リポジトリに格納されているスクリプトを指定します。格納されたスクリプトには、スクリプトの実行時に適用する関数が含まれます。すべてのOracle R Enterpriseユーザーが、埋込みR関数の呼出し時にFUN.NAME
引数を使用できます。
OREmodels
パッケージのOracle R Enterpriseの高度な分析関数であるore.glm
、ore.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.graphics
がTRUE
の場合に、png
グラフィック・ドライバの追加引数を指定します。これらの引数のネーミング規則では、png
関数の引数にore.png.
接頭辞を追加します。たとえば、ore.png.height
を指定すると、引数height
がpng
関数に渡されます。設定しない場合は、png
関数に標準のデフォルト値が使用されます。
すべての埋込みRの実行関数に適用されるもう1つの引数にFUN.VALUE
があります。FUN.VALUE
引数がNULL
の場合、ore.doEval
関数およびore.tableApply
関数はore.object
クラス・オブジェクトとしてシリアライズRオブジェクトを返し、ore.groupApply
、ore.indexApply
およびore.rowApply
の各関数はore.list
オブジェクトを返します。ただし、data.frame
またはore.frame
にFUN.VALUE
引数を指定した場合、この関数は、指定したdata.frame
オブジェクトまたはore.frame
オブジェクトの構造を持つore.frame
を返します。
ore.doEval
関数およびore.indexApply
関数は、データベースから自動的にデータを受け取りません。FUN
引数またはFUN.NAME
引数で指定された関数を単純に実行します。入力関数で必要なすべてのデータは、その関数内で生成されるか、Oracle Database、その他のデータベースまたはフラット・ファイルなどのデータ・ソースから明示的に取得するかのいずれかです。入力関数は、ore.pull
関数またはその他の透過層関数を使用して、ファイルまたは表からデータをロードできます。
ore.tableApply
、ore.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.groupApply
、ore.indexApply
およびore.rowApply
の各関数は、parallel
引数を取ります。この引数には、入力関数の埋込みRの実行で使用するための並列度を指定します。「パラレル実行のサポート」を参照してください。
ore.groupApply
、ore.indexApply
およびore.rowApply
の各関数は、関数に固有の引数を取ります。
ore.groupApply
関数はINDEX
引数を取り、これには、入力データの行が入力関数での処理のためにパーティショニングされる列の名前を指定します。
ore.indexApply
関数はtimes
引数を取り、これには、入力関数を実行する回数を指定します。
ore.rowApply
関数はrows
引数を取り、これには、入力関数の各呼出しに渡す行の数を指定します。
埋込み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.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
doEval
関数のオプションの引数として入力関数に引数を指定できます。例6-4では、RandomRedDots
関数のdivisor引数をオーバーライドするオプションの引数を指定してdoEval
関数を呼び出します。
例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.connect
をTRUE
に設定します。接続を確立して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.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.frame
をdat
引数として入力関数に渡します。この入力関数は、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.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ディシジョン・ツリー・モデルをC50
のchurn
データセットに構築します。この例では、次の操作を実行しています。
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.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
としてデータベースにプッシュします。
IRIS
をIRIS_PRED
としてコピーし、予測を含めるためにPRED列をIRIS_PRED
に追加します。
ore.rowApply
関数を呼び出し、IRIS
のore.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
関数は、入力関数によって生成されたデータを使用して指定されたユーザー定義の入力関数を実行します。これは、1つ以上のRエンジンが同じまたは異なる計算(タスク)を実行するタスク・パラレル実行をサポートします。ore.indexApply
関数に対するtimes
引数には、データベース内で入力関数を実行する回数を指定します。必要なすべてのデータは、入力関数内で明示的に生成またはロードされる必要があります。
ore.indexApply
関数は、ore.list
オブジェクトまたはore.frame
オブジェクトを返します。
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.simulations
をore.indexApply
関数の最初の引数として指定します。ore.indexApply
関数は、num.simulations
をindex
引数としてユーザー定義の関数に渡します。この入力関数はその後、各入力関数の呼出しで異なる乱数値のセットが生成されるように、索引に基づいて乱数シードを設定します。
次に、入力関数は、rnorm
関数を使用してsample.size
ランダムな標準値を生成します。乱数のベクターでsummary
関数を呼び出し、返される結果としてdata.frame
を準備します。ore.indexApply
関数には、シミュレーションの結合された結果を構成するore.frame
を返すように、FUN.VALUE
引数を指定します。res
変数は、ore.indexApply
関数によって返されるore.frame
を取得します。
サンプルの分布を取得するために、この例では、ore.pull
関数を使用した結果であるdata.frame
でboxplot
関数を呼び出し、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
関数は、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")
Oracle R Enterpriseの埋込みRの実行用のSQLインタフェースでは、本番データベースのアプリケーションでRスクリプトを実行できます。
SQLインタフェースで使用する関数は、データベースRリポジトリに格納し、SQLのAPI関数の名前で参照する必要があります。リポジトリにスクリプトを追加する方法、リポジトリからスクリプトを削除する方法、およびリポジトリ内のスクリプトの一覧を表示して使用する方法については、「SQLスクリプトの登録および管理」を参照してください。
SQL関数についての説明は、「Oracle R EnterpriseのSQL関数について」を参照してください。
この項では、SQLインタフェースについて、次の各項で説明します。
埋込みRの実行用のSQLインタフェースで使用するR関数は、データベースのRスクリプト・リポジトリに格納し、SQLのAPI関数の名前で参照する必要があります。セキュリティ上の理由により、最初にシステムで一意の名前でRスクリプトを登録し、SQLインタフェース表関数へのコールで実際のスクリプトのかわりに新しい名前を使用する必要があります。
管理用の関数sys.rqScriptCreate
およびsys.rqScriptDrop
は、スクリプトを作成および削除します。sys.rq_scripts
ビューによって、作成したスクリプトをリストおよび使用できます。
スクリプトの作成または削除には、「スクリプトのセキュリティに関する考慮事項」で説明するRQADMINロールが必要です。
sys.rqScriptCreate
を使用する場合は、関数文字列の対応するR閉包を指定する必要があります。
例6-16に、Rスクリプトの登録および使用を示します。
Oracle R EnterpriseのSQL関数を呼び出すと、データベースの並列性設定に基づいて、1つ以上のRエンジンがデータベースで起動されます。データベースでのRスクリプトの実行を有効化するために、Oracle R Enterpriseでは、ore.doEval
、ore.tableApply
、ore.groupApply
およびore.rowApply
の各関数のSQLバリアントを提供しています。これらのR関数については、「埋込みRの実行用のRインタフェース」で説明しています。
rqTableEval
rqEval
rqRowEval
rqGroupEval
rqGroupEval
関数には追加のSQL指定が必要で、ここでは、指定された列の値に従ってデータをパーティショニングし、各パーティションでRスクリプトを起動する仮想関数として提供されます。詳細は、「rqGroupEval関数の使用方法」を参照してください。
また、「SQLでのデータストア管理」で説明するように、これらの関数をデータストア内のオブジェクトとともに使用できます。
rqEval
、rqTableEval
、rqGroupEval
および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-name
はrqGroupEval
に適用され、グループ化列の名前を指定します。
num_rows
はrqRowEval
に適用され、関数に一度に渡す行の数を指定します。
<R closure name of registered-R-code>は、実行するR関数の登録済バージョンです。詳細は、「SQLスクリプトの登録および管理」を参照してください。
すべてのSQL関数の戻り値は、次のいずれかの値を示します。
SELECT文に指定された表のシグネチャ。rq
関数からの結果を表として返します。
XML: 1つのXML文字列で構造化イメージとグラフ・イメージの両方を含むCLOBとして返します。最初に構造化されたコンポーネントが提供され、次にbase 64でエンコードされたイメージのpng
表示が続きます。
PNG: png
形式でグラフ・イメージを含むBLOBとして返します。
rqEval
、rqTableEval
、rqGroupEval
および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
関数は、グループ化列によってパーティショニングされたデータ上で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
句はオプションではありません。
埋込み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;
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';