ore.rowApply関数は、入力データとしてore.frameを指定してRスクリプトを起動します。ore.rowApply関数は、ore.frameを最初の引数としてユーザー定義の入力関数に渡します。ore.rowApply関数に対するrows引数には、ユーザー定義のR関数の呼出しごとに渡す行の数を指定します。最後のチャンクまたは行は、指定した数より少なくなる可能性があります。ore.rowApply関数は、1つ以上のRエンジンが同じR関数(タスク)をデータの別のパーティションで実行するデータ・パラレル実行を使用できます。
ore.rowApply関数の構文は次のとおりです。
ore.rowApply(X, FUN, ..., FUN.VALUE = NULL, FUN.NAME = NULL, rows = 1, FUN.OWNER = NULL,
parallel = getOption("ore.parallel", NULL))
ore.rowApply関数は、ore.listオブジェクトまたはore.frameオブジェクトを返します。
関連項目:
関数ore.rowApplyの引数の詳細は、「スクリプトを実行する関数の引数」を参照してください。
例6-15では、事前にCRANからダウンロードしてあるe1071パッケージを使用します。また、この例では、例6-12で作成したNaive Bayesモデルであるnbmodオブジェクトも使用します。
例6-15では、次の処理を行います。
パッケージe1071をロードします。
irisデータセットをIRIS一時表およびore.frameオブジェクトとしてデータベースにプッシュします。
IRISをIRIS_PREDとしてコピーし、予測を含めるためにPRED列をIRIS_PREDに追加します。
ore.rowApply関数を呼び出し、IRIS ore.frameをユーザー定義R関数のデータソースおよびユーザー定義R関数自体として渡します。
ユーザー定義の関数は、次のことを実行します。
パッケージe1071を、データベース内で稼働するRエンジンまたはエンジンで使用できるようにロードします。
ore.frameはファクタを定義しますが、ユーザー定義の関数にロードされたときにファクタが文字列ベクターとして表示されるため、Species列をファクタに変換します。
predictメソッドを起動し、データセットに追加された列に予測が含まれているresオブジェクトを返します。
この例では、モデルをクライアントのRセッションにプルします。
IRIS_PREDを引数FUN.VALUEとして渡しますが、この引数にore.rowApply関数が返すオブジェクトの構造を指定します。
ユーザー定義関数の呼出しごとに渡す行の数を指定します。
resのクラスを表示し、table関数を呼び出してSpecies列およびresオブジェクトのPRED列を表示します。
例6-15 ore.rowApply関数の使用方法
library(e1071)
IRIS <- ore.push(iris)
IRIS_PRED <- IRIS
IRIS_PRED$PRED <- "A"
res <- ore.rowApply(
IRIS,
function(dat, nbmod) {
library(e1071)
dat$Species <- as.factor(dat$Species)
dat$PRED <- predict(nbmod, newdata = dat)
dat
},
nbmod = ore.pull(nbmod),
FUN.VALUE = IRIS_PRED,
rows = 10)
class(res)
table(res$Species, res$PRED)
例6-15のリストR> library(e1071)
R> IRIS <- ore.push(iris)
R> IRIS_PRED <- IRIS
R> IRIS_PRED$PRED <- "A"
R> res <- ore.rowApply(
+ IRIS ,
+ function(dat, nbmod) {
+ library(e1071)
+ dat$Species <- as.factor(dat$Species)
+ dat$PRED <- predict(nbmod, newdata = dat)
+ dat
+ },
+ nbmod = ore.pull(nbmod),
+ 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
例6-16では、例6-13と同様にC50パッケージを使用し、C5.0モデルを使用してチャーン・データをスコアリングします(つまり、解約傾向が高い顧客を予測します)。ただし、例6-16では、列によってデータをパーティショニングするのではなく、多数の行によってデータをパーティショニングします。この例では、指定された状態からの顧客を並行してスコアリングします。データストアを使用し、関数をOracle R EnterpriseのRスクリプト・リポジトリに保存することにより、これらの関数をOracle R Enterprise SQL API関数で使用できるようにします。
例6-16ではまず、C50パッケージおよびデータセットをロードします。この例では、名前にmyC5.0modelFLが含まれるデータストアが存在する場合、そのデータストアを削除します。ore.dropを呼び出してCHURN_TEST表(存在する場合)を削除した後、ore.createを呼び出してchurnTestデータセットからCHURN_TEST表を作成します。
次に、ファクタ列ごとにレベルのlistを返すore.getLevelsを呼び出します。この呼出しでは、最初の列(state)のレベルは必要ないため最初の列は除外されます。最初にレベルを取得しておくと、モデル構築中に、一部のレベルに対して値を持たない行があっても、すべての使用可能なレベルを確実に取得できます。ore.deleteの呼出しによって、指定された名前のデータストアが存在しないことが確認され、ore.saveの呼出しによって、xlevelsオブジェクトがmyXLevelsという名前のデータストアに保存されます。
例6-16では、C5.0モデルを生成するユーザー定義関数myC5.0FunctionForLevelsを作成します。この関数は、例6-13のようにas.factor関数をユーザー定義関数として使用してレベルを計算するのではなく、関数ore.getXlevelsにより返されたレベルのリストを使用します。レベルを使用して、列タイプを文字ベクターからファクタに変換します。関数myC5.0FunctionForLevelsは、値TRUEを返します。この例では、この関数をOracle R EnterpriseのRスクリプト・リポジトリに保存します。
次に、指定された文字列を含む名前のデータストアのリストを取得し、これらのデータストアが存在していれば削除します。
その後、ore.groupApplyを呼び出し、それによってCHURN_TESTデータの各状態に対して関数myC5.0FunctionForLevelsが呼び出されます。myC5.0FunctionForLevelsの呼出しのたびに、ore.groupApplyは、xlevelsオブジェクトを含むデータストアと、myC5.0FunctionForLevelsにより生成されたデータストアのネーミングに使用する接頭辞を渡します。また、ore.connect制御引数を渡して埋込みR関数でデータベースに接続することにより、データストアに格納されているオブジェクトを使用できるようにします。ore.groupApplyの呼出しにより、myC5.0FunctionForLevelsのすべての呼出しの結果を含むリストが返されます。
この例では、結果をローカルなRセッションにプルし、データソース内の各状態に対してmyC5.0FunctionForLevelsがTRUEを返したことを確認します。
例6-16では次に、別のユーザー定義関数myScoringFunctionを作成し、Oracle R EnterpriseのRスクリプト・リポジトリに格納します。この関数は、状態のレベルでC5.0モデルをスコアリングし、結果をdata.frameで返します。
次に、関数ore.rowApplyを呼び出します。マサチューセッツ州のデータのみを使用するように入力データをフィルタ処理します。呼び出す関数としてmyScoringFunctionを指定し、xlevelsオブジェクトを含むデータストアの名前と、状態に対するC5.0モデルを含むデータストアをロードする際に使用する接頭辞をそのユーザー定義関数に渡します。ore.rowApplyの呼出しにより、各パラレルRエンジンでデータセット200行に対してmyScoringFunctionを呼び出すことを指定します。ore.rowApplyがmyScoringFunctionのすべての呼出しの結果を含むore.frameを返すように、FUN.VALUE引数を使用します。変数scoresは、ore.rowApply呼出しの結果を取得します。
例6-16では最後に、scoresオブジェクトを出力した後、表関数を使用してスコアリング用の混同マトリクスを表示します。
例6-16 データストアおよびスクリプトを指定したore.rowApply関数の使用方法
library(C50)
data(churn)
ore.drop("CHURN_TEST"
ore.create(churnTest, "CHURN_TEST")
xlevels <- ore.getXlevels(~ ., CHURN_TEST[,-1])
ore.delete("myXLevels")
ore.save(xlevels, name = "myXLevels")
ore.scriptDrop("myC5.0FunctionForLevels")
ore.scriptCreate("myC5.0FunctionForLevels",
function(dat, xlevelsDatastore, datastorePrefix) {
library(C50)
state <- dat[1,"state"]
datastoreName <- paste(datastorePrefix, dat[1, "state"], sep = "_")
dat$state <- NULL
ore.load(name = xlevelsDatastore)
for (j in names(xlevels))
dat[[j]] <- factor(dat[[j]], levels = xlevels[[j]])
c5mod <- C5.0(churn ~ ., data = dat, rules = TRUE)
ore.save(c5mod, name = datastoreName)
TRUE
})
ds.v <- ore.datastore(pattern= "myC5.0modelFL")$datastore.name
for (ds in ds.v) ore.delete(name = ds)
res <- ore.groupApply(CHURN_TEST,
INDEX=CHURN_TEST$state,
FUN.NAME = "myC5.0FunctionForLevels",
xlevelsDatastore = "myXLevels",
datastorePrefix = "myC5.0modelFL",
ore.connect = TRUE)
res <- ore.pull(res)
all(as.logical(res) == TRUE)
ore.scriptDrop("myScoringFunction")
ore.scriptCreate("myScoringFunction",
function(dat, xlevelsDatastore, datastorePrefix) {
library(C50)
state <- dat[1,"state"]
datastoreName <- paste(datastorePrefix,state,sep="_")
dat$state <- NULL
ore.load(name = xlevelsDatastore)
for (j in names(xlevels))
dat[[j]] <- factor(dat[[j]], levels = xlevels[[j]])
ore.load(name = datastoreName)
res <- data.frame(pred = predict(c5mod, dat, type = "class"),
actual = dat$churn,
state = state)
res
}
)
scores <- ore.rowApply(
CHURN_TEST[CHURN_TEST$state == "MA",],
FUN.NAME = "myScoringFunction",
xlevelsDatastore = "myXLevels",
datastorePrefix = "myC5.0modelFL",
ore.connect = TRUE, parallel = TRUE,
FUN.VALUE = data.frame(pred = character(0),
actual = character(0),
state = character(0)),
rows=200)
scores
table(scores$actual, scores$pred)
例6-16のリストR> library(C50)
R> data(churn)
R>
R> ore.drop("CHURN_TEST"
R> ore.create(churnTest, "CHURN_TEST")
R>
R> xlevels <- ore.getXlevels(~ ., CHURN_TEST[,-1])
R> ore.delete("myXLevels")
[1] "myXLevels
R> ore.save(xlevels, name = "myXLevels")
R>
R> ore.scriptDrop("myC5.0FunctionForLevels")
R> ore.scriptCreate("myC5.0FunctionForLevels",
+ function(dat, xlevelsDatastore, datastorePrefix) {
+ library(C50)
+ state <- dat[1,"state"]
+ datastoreName <- paste(datastorePrefix, dat[1, "state"], sep = "_")
+ dat$state <- NULL
+ ore.load(name = xlevelsDatastore)
+ for (j in names(xlevels))
+ dat[[j]] <- factor(dat[[j]], levels = xlevels[[j]])
+ c5mod <- C5.0(churn ~ ., data = dat, rules = TRUE)
+ ore.save(c5mod, name = datastoreName)
+ TRUE
+ })
R>
R> ds.v <- ore.datastore(pattern="myC5.0modelFL")$datastore.name
R> for (ds in ds.v) ore.delete(name=ds)
R>
R> res <- ore.groupApply(CHURN_TEST,
+ INDEX=CHURN_TEST$state,
+ FUN.NAME="myC5.0FunctionForLevels",
+ xlevelsDatastore = "myXLevels",
+ datastorePrefix = "myC5.0modelFL",
+ ore.connect = TRUE)
R> res <- ore.pull(res)
R> all(as.logical(res) == TRUE)
[1] TRUE
R>
R> ore.scriptDrop("myScoringFunction")
R> ore.scriptCreate("myScoringFunction",
+ function(dat, xlevelsDatastore, datastorePrefix) {
+ library(C50)
+ state <- dat[1,"state"]
+ datastoreName <- paste(datastorePrefix,state,sep="_")
+ dat$state <- NULL
+ ore.load(name = xlevelsDatastore)
+ for (j in names(xlevels))
+ dat[[j]] <- factor(dat[[j]], levels = xlevels[[j]])
+ ore.load(name = datastoreName)
+ res <- data.frame(pred = predict(c5mod, dat, type="class"),
+ actual = dat$churn,
+ state = state)
+ res
+ }
+ )
R>
R> scores <- ore.rowApply(
+ CHURN_TEST[CHURN_TEST$state =="MA",],
+ FUN.NAME = "myScoringFunction",
+ xlevelsDatastore = "myXLevels",
+ datastorePrefix = "myC5.0modelFL",
+ ore.connect = TRUE, parallel = TRUE,
+ FUN.VALUE = data.frame(pred=character(0),
+ actual=character(0),
+ state=character(0)),
+ rows=200
R>
R> scores
pred actual state
1 no no MA
2 no no MA
3 no no MA
4 no no MA
5 no no MA
6 no yes MA
7 yes yes MA
8 yes yes MA
9 no no MA
10 no no MA
11 no no MA
12 no no MA
13 no no MA
14 no no MA
15 yes yes MA
16 no no MA
17 no no MA
18 no no MA
19 no no MA
20 no no MA
21 no no MA
22 no no MA
23 no no MA
24 no no MA
25 no no MA
26 no no MA
27 no no MA
28 no no MA
29 no yes MA
30 no no MA
31 no no MA
32 no no MA
33 yes yes MA
34 no no MA
35 no no MA
36 no no MA
37 no no MA
38 no no MA
Warning message:
ORE object has no unique key - using random order
R> table(scores$actual, scores$pred)
no yes
no 32 0
yes 2 4