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.groupApply(X, INDEX, FUN, ..., FUN.VALUE = NULL, FUN.NAME = NULL, FUN.OWNER = NULL, parallel = getOption("ore.parallel", NULL))
ore.groupApply
関数は、ore.list
オブジェクトまたはore.frame
オブジェクトを返します。
ore.groupApply
関数の使用例は、次の各項で説明します。
関連項目:
関数ore.groupApply
の引数の詳細は、「スクリプトを実行する関数の引数」を参照してください。
例6-13では、ディシジョン・ツリーおよびルールベース・モデルを構築する関数が含まれるC50
パッケージを使用します。このパッケージには、トレーニング・データとテスト・データのセットも含まれています。例6-13では、状態ごとのデータに基づいて1つのチャーン・モデルを作成することを目的に、C50
パッケージのchurn
データセットからのchurnTrain
トレーニング・データセットに基づいてC5.0モデルを構築します。この例では、次の操作を実行しています。
C50
パッケージをロードした後に、churn
データセットをロードします。
ore.create
関数を使用して、churnTrain
(data.frame
オブジェクト)からCHURN_TRAIN
データベース表およびそのプロキシore.frame
オブジェクトを作成します。
CHURN_TRAIN
(プロキシore.frame
オブジェクト)をore.groupApply
関数の最初の引数として指定し、state
列をINDEX
引数として指定します。ore.groupApply
関数は、state
列のデータをパーティショニングし、ユーザー定義の関数を各パーティションで呼び出します。
ore.groupApply
関数によって返されるore.list
オブジェクトを取得するための変数modList
を作成します。ore.list
オブジェクトには、データの各パーティションでユーザー定義の関数を実行した結果が含まれています。この場合は、状態ごとに1つのC5.0モデルで、各モデルはore.object
オブジェクトとして格納されています。
ユーザー定義の関数を指定します。ユーザー定義の関数の最初の引数は、データ(1つの状態に関連付けられたすべてのデータ)の1つのパーティションを受け取ります。
ユーザー定義の関数は、次のことを実行します。
データベースのRエンジンで起動したときに関数で使用できるように、C50パッケージをロードします。
state
列がモデルに含まれないように、data.frame
からこの列を削除します。
ore.frame
はファクタを定義しますが、ユーザー定義の関数にロードされたときにファクタが文字列ベクターとして表示されるため、列をファクタに変換します。
状態のモデルを構築し、それを返します。
ore.pull
関数を使用してデータベースからmod.MA
変数としてモデルを取得し、そこでsummary
関数を呼び出します。mod.MA
のクラスはC5.0
です。
例6-13 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-13のリスト
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つの列または複数の列を取ります。
例6-14は、CHURN_TRAIN
データセットのデータを使用して、指定したデータのパーティション(voice_mail_plan
列およびinternational_plan
列)に対するルールを作成するrpart
モデルを構築します。この例では、Rのtable
関数を使用して各パーティションで予測される行の数を示します。
この例では次に、指定された名前のスクリプトがOracle DatabaseのRスクリプト・リポジトリに存在しないようにするために、ore.scriptDrop
関数を呼び出します。その後、ore.scriptCreate
関数を使用してmy_rpartFunction
という名前のスクリプトを定義し、それをリポジトリに格納します。格納されたスクリプトでは、Oracle R Enterpriseのデータストア・オブジェクトの命名に使用されるデータ・ソースおよび接頭辞を使用する関数を定義します。関数my_rpartFunction
の各呼出しは、voice_mail_planおよびinternational_plan列の値によって特定されたパーティションのいずれかからデータを受け取ります。ソース・パーティションの列は定数のため、この関数はそれらをNULL
に設定します。文字列ベクターをファクタに変換し、流動を予測するためのモデルを構築し、そこに適切に命名されたデータストアを保存します。この関数は、特定のパーティション列値、流動値の分布およびモデル自身を返すためのリストを作成します。
次にrpart
ライブラリをロードし、データストアの接頭辞を設定し、INDEX
引数としてvoice_mail_planおよびinternational_plan列の値を、Rスクリプト・リポジトリに格納されているユーザー定義関数を呼び出すためのFUN.NAME
引数の値としてmy_rpartFunction
を使用して、ore.groupApply
を呼び出します。ore.groupApply
関数は、オプションの引数を使用してdatastorePrefix
変数をユーザー定義の関数に渡します。この関数は、ユーザー定義の関数の実行時に、オプションの引数ore.connect
を使用してデータベースに接続します。ore.groupApply
関数は、変数res
としてore.list
オブジェクトを返します。
この例では、返されるリストの最初のエントリを表示します。次に、ore.load
関数を呼び出して、顧客がボイス・メール・プランと国際プランの両方を持つ場合のモデルをロードします。
例6-14 複数列でデータをパーティションする場合の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) options(width = 80) head(CHURN_TRAIN, 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(CHURN_TRAIN, INDEX = CHURN_TRAIN[, c("voice_mail_plan", "international_plan")], FUN.NAME = "my_rpartFunction", datastorePrefix = datastorePrefix, ore.connect = TRUE) res[[1]] ore.load(name=paste(datastorePrefix, "yes", "yes", sep = "_")) mod例6-14のリスト
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> R> options(width = 80) R> head(CHURN_TRAIN, 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 1 2.70 1 no 2 3.70 1 no 3 3.29 0 no Warning messages: 1: ORE object has no unique key - using random order 2: ORE object has no unique key - using random order 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(CHURN_TRAIN, + INDEX = CHURN_TRAIN[, c("voice_mail_plan", "international_plan")], + 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) *