10.5.4 pyqRowEvalファンクション(オンプレミス・データベース)

このトピックでは、オンプレミスOracle Databaseで使用されるpyqRowEvalファンクションについて説明します。pyqRowEvalファンクションは、データを一連の行にチャンク化した後、各チャンクに対してユーザー定義Python関数を実行します。

pyqRowEvalファンクションは、INP_NAMパラメータで指定されたデータを、EXP_NAMパラメータで指定されたPython関数に渡します。PAR_QRYパラメータを使用して、引数をPython関数に渡すことができます。

ROW_NUMパラメータでは、Python関数の各呼出しに渡す最大行数を指定します。最後の行セットの行は、指定した数より少なくなることがあります。

Python関数は、booleandictfloatintliststrtupleまたはpandas.DataFrameオブジェクトを返すことができます。OUT_QRYパラメータを使用して、返される値の形式を定義できます。

構文

pyqRowEval (
    INP_NAM     VARCHAR2       IN
    PAR_QRY     VARCHAR2       IN
    OUT_QRY     VARCHAR2       IN
    ROW_NUM     NUMBER         IN
    EXP_NAM     VARCHAR2       IN)

パラメータ

パラメータ 説明

INP_NAM

EXP_NAMパラメータで指定されたPython関数に渡すデータを指定する表またはビューの名前。別のユーザーが所有する表またはビューを使用する場合は、<owner name>.<table/view name>という形式を使用します。指定された表またはビューに対する読取りアクセス権が必要です。

PAR_QRY

EXP_NAMパラメータで指定されたユーザー定義Python関数に渡す追加パラメータが含まれるJSON文字列。oml_で始まる特殊な制御引数は、EXP_NAMで指定された関数に渡されるのではなく、関数の呼出し前後の動作を制御します。

たとえば、入力データ型をpandas.DataFrameとして指定するには、次を使用します。

'{"oml_input_type":"pandas.DataFrame"}'

OUT_QRY

ファンクションによって返される出力の形式。次のいずれかになります。

  • ファンクションによって返された表の列名およびデータ型を指定するJSON文字列。イメージ・データは破棄されます。
  • プロトタイプとして使用する表またはビューの名前。別のユーザーが所有する表またはビューを使用する場合は、<owner name>.<table/view name>という形式を使用します。指定された表またはビューに対する読取りアクセス権が必要です。
  • 文字列'XML'。返される表にXML文字列であるCLOBが含まれることを指定します。XMLには構造化データとイメージの両方が含まれる可能性があり、最初に構造化または半構造化のPythonオブジェクトが含まれ、続いてPython関数によって生成されたイメージが含まれます。
  • 文字列'PNG'。返される表に、Python関数によって生成されたイメージを格納するBLOBが含まれることを指定します。イメージはPNG表示のbase 64エンコーディングとして返されます。
ROW_NUM

Python関数の各呼出しに含める行数。

EXP_NAM

OML4Pyスクリプト・リポジトリ内のユーザー定義Python関数の名前。

戻り値

ファンクションpyqRowEvalは、OUT_QRYパラメータ値で指定された構造を持つ表を返します。

例10-17 pyqRowEvalファンクションの使用方法

次の例では、サンプルのirisデータの行チャンクを予測するために、Pythonモデルlinregrをロードします。モデルが作成され、例10-16のデータストアpymodelに保存されます。

この例では、Python関数を定義し、OML4Pyスクリプト・リポジトリに格納します。ユーザー定義Python関数を使用して、pyqEval関数の結果としてデータベース表を作成します。OML4Pyデータストアからロードされたモデルに対して予測関数を実行するPython関数を定義します。次に、pyqTableEvalファンクションを呼び出して、データベース表の行のチャンクに対して関数を呼び出します。

PL/SQLブロックで、関数sample_iris_tableを定義し、スクリプト・リポジトリに格納します。この関数は、irisデータ・セットをロードし、2つのpandas.DataFrameオブジェクトを作成し、これらのオブジェクトの連結のサンプルを返します。

BEGIN
  sys.pyqScriptCreate('sample_iris_table',
    'def sample_iris_table(size):
       from sklearn.datasets import load_iris
       import pandas as pd
       iris = load_iris()
       x = pd.DataFrame(iris.data, columns = ["Sepal_Length",\
                        "Sepal_Width","Petal_Length","Petal_Width"])
       y = pd.DataFrame(list(map(lambda x: {0:"setosa", 1: "versicolor",\
                                 2: "virginica"}[x], iris.target)),\
                        columns = ["Species"])
       return pd.concat([y, x], axis=1).sample(int(size))',
     FALSE, TRUE);  -- V_GLOBAL, V_OVERWRITE
END;
/

SELECT文の結果としてデータベースでSAMPLE_IRIS表を作成します。この文は、同じ名前でスクリプト・リポジトリに保存されたsample_iris_tableユーザー定義Python関数に対してpyqEval関数を呼び出します。sample_iris_table関数は、サイズsizeのirisデータのサンプルを返します。

CREATE TABLE sample_iris AS
SELECT *
  FROM TABLE(pyqEval(
               '{"size":20}',
               '{"Species":"varchar2(10)","Sepal_Length":"number",
                "Sepal_Width":"number","Petal_Length":"number",
                "Petal_Width":"number"}',
                'sample_iris_table'));

Python関数predict_modelを定義し、linregrPredictという名前でスクリプト・リポジトリに格納します。この関数は、modelName引数で指定されたPythonモデルを使用して、datのデータを予測します。これは、datastoreName引数で指定されたデータストアからロードされます。予測は最終的に連結され、関数が返すオブジェクトとしてdatを使用して返されます。

BEGIN
  sys.pyqScriptCreate('linregrPredict',
    'def predict_model(dat, modelName, datastoreName):
       import oml
       import pandas as pd
       objs = oml.ds.load(name=datastoreName, to_globals=False)
       pred = objs[modelName].predict(dat[["Sepal_Length","Sepal_Width",\
                                           "Petal_Length"]])
       return pd.concat([dat, pd.DataFrame(pred, \
                         columns=["Pred_Petal_Width"])], axis=1)',
     FALSE, TRUE);
END;
/

pyqRowEvalファンクションを呼び出すSELECT文を実行して、指定されたデータ・セット内の各行チャンクに対して指定されたPython関数を実行します。

INP_NAM引数では、Python関数に渡すSAMPLE_IRIS表のデータを指定します。

PAR_QRY引数では、特殊な制御引数oml_connectを使用してOML4Pyサーバーに接続し、特別な制御引数oml_input_typeを使用して入力データをpandas.DataFrameとして、関数の引数modelNameおよびdatastoreNameの値とともに渡すことを指定します。

OUT_QRY引数では、JSON文字列でpyqRowEvalによって返される表の列名およびデータ型を指定します。

ROW_NUM引数では、EXP_NAMで指定された関数の呼出しごとに5行を含めることを指定します。

EXP_NAMパラメータでは、linregrPredictを指定します。これは、呼び出すユーザー定義Python関数のスクリプト・リポジトリ内の名前です。

SELECT *
  FROM table(pyqRowEval(
     'SAMPLE_IRIS',
     '{"oml_connect":1,"oml_input_type":"pandas.DataFrame",
       "modelName":"linregr", "datastoreName":"pymodel"}',
     '{"Species":"varchar2(10)", "Sepal_Length":"number",
       "Sepal_Width":"number", "Petal_Length":"number",   
       "Petal_Width":"number","Pred_Petal_Width":"number"}',
     5,
     'linregrPredict'));

出力は次のようになります。

Species    Sepal_Length Sepal_Width Petal_Length Petal_Width Pred_Petal_Width
---------- ------------ ----------- ------------ ----------- ------------------
versicolor          5.4           3          4.5         1.5  1.66731546068336
versicolor            6         3.4          4.5         1.6  1.63208723397328
setosa              5.5         4.2          1.4         0.2  0.289325450127603
virginica           6.4         3.1          5.5         1.8  2.00641535609046
versicolor          6.1         2.8          4.7         1.2  1.58248012323666
setosa              5.4         3.7          1.5         0.2  0.251046097050724
virginica           7.2           3          5.8         1.6  1.97554457713195
versicolor          6.2         2.2          4.5         1.5  1.32323976658868
setosa              4.8         3.1          1.6         0.2  0.294116926466465
virginica           6.7         3.3          5.7         2.5  2.0936178656911
virginica           7.2         3.6          6.1         2.5  2.26646663788204
setosa                5         3.6          1.4         0.2  0.259261360689759
virginica           6.3         3.4          5.6         2.4  2.14639883810232
virginica           6.1           3          4.9         1.8  1.73186245496453
versicolor          6.1         2.9          4.7         1.4  1.60476297762276
versicolor          5.7         2.8          4.5         1.3  1.56056992978395
virginica           6.4         2.7          5.3         1.9  1.8124673155904
setosa                5         3.5          1.3         0.3  0.184570194825823
versicolor          5.6         2.7          4.2         1.3  1.40178874834007
setosa              4.5         2.3          1.3         0.3  0.0208089790714202