11.7.2.4 pyqRowEvalファンクション(Autonomous Database)

ファンクションpyqRowEvalは、Oracle Autonomous Databaseで使用すると、データを一連の行にチャンク化した後、各チャンクに対してユーザー定義Python関数を実行します。

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

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

構文

FUNCTION PYQSYS.pyqRowEval(
    INP_NAM    VARCHAR2,
    PAR_LST    VARCHAR2,
    OUT_FMT    VARCHAR2,
    ROW_NUM    NUMBER,
    SCR_NAME   VARCHAR2,
    SCR_OWNER  VARCHAR2 DEFAULT NULL,
    ENV_NAME   VARCHAR2 DEFAULT NULL 
    )
    RETURN SYS.AnyDataSet

パラメータ

パラメータ 説明

INP_NAM

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

PAR_LST

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

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

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

関連項目: 特殊な制御引数(Autonomous Database)

OUT_FMT

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

  • ファンクションによって返された表の列名およびデータ型を指定するJSON文字列。イメージ・データは破棄されます。Python関数は、pandas.DataFramenumpy.ndarraytupleまたはtupleのリストを返す必要があります。
  • 文字列'JSON'。返される表にJSON文字列であるCLOBが含まれることを指定します。

  • 文字列'XML'。返される表にXML文字列であるCLOBが含まれることを指定します。XMLには構造化データとイメージの両方が含まれる可能性があり、最初に構造化または半構造化のPythonオブジェクトが含まれ、続いてPython関数によって生成されたイメージが含まれます。
  • 文字列'PNG'。返される表に、Python関数によって生成されたイメージを格納するBLOBが含まれることを指定します。イメージはPNG表示のbase 64エンコーディングとして返されます。

関連項目: 出力形式(Autonomous Database)

ROW_NUM

チャンク内の行の数。Pythonスクリプトは各チャンクで実行されます。

SCR_NAME

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

SCR_OWNER

登録済Pythonスクリプトの所有者。デフォルト値はNULLです。NULLの場合、ユーザーのスクリプト・リポジトリでPythonスクリプトを検索します。

ENV_NAME

指定されたユーザー定義Python関数の実行時に使用されるconda環境の名前。

この例では、指定されたデータ・セット内の各行チャンクに対し、指定されたPythonスクリプトを実行するpyqRowEvalファンクションをコールします。

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

PAR_LST引数は、特殊な制御引数oml_graphics_flagを使用してスクリプトでレンダリングされたイメージを取得することを指定します。

OUT_FMT引数は、Python関数によって生成されたイメージが格納されたBLOBが含まれる表を返すことを指定します。

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

SCR_NAMEパラメータは、pyqTableEvalファンクション(Autonomous Database)で作成される'test_seaborn_inp'スクリプトを指定します。

ENV_NAMEパラメータは、pyqEvalファンクション(Autonomous Database)で作成されるConda環境である'seaborn'を指定します。

select *
  from table(pyqRowEval(
        inp_nam =>  'IRIS',
        par_lst => '{"oml_graphics_flag":true}',
        out_fmt => 'PNG',
        row_num => 50,
        scr_name => 'test_seaborn_inp',
        scr_owner => NULL,
        env_name => 'seaborn'
));

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

NAME
--------------------------------------------------------------------------------
        ID
----------
VALUE
--------------------------------------------------------------------------------
TITLE
--------------------------------------------------------------------------------
IMAGE
--------------------------------------------------------------------------------
CHUNK_1
         1
"hello world"

NAME
--------------------------------------------------------------------------------
        ID
----------
VALUE
--------------------------------------------------------------------------------
TITLE
--------------------------------------------------------------------------------
IMAGE
--------------------------------------------------------------------------------
Iris plot
89504E470D0A1A0A0000000D4948445200000280000001E0080600000035D1DCE400000039744558
74536F667477617265004D6174706C6F746C69622076657273696F6E332E332E332C206874747073

NAME
--------------------------------------------------------------------------------
        ID
----------
VALUE
--------------------------------------------------------------------------------
TITLE
--------------------------------------------------------------------------------
IMAGE
--------------------------------------------------------------------------------
3A2F2F6D6174706C6F746C69622E6F72672FC897B79C000000097048597300000F6100000F6101A8
3FA7690000812549444154789CEDDD7774D5F5FD3FF0E767DC99BD13C82081B0041450101C888A0A
54455B57ADA3167F75B46AF5EBB7DA6FADB5D6E2AAA3B52A6A155A6B69B56A97685DE0420501058A

NAME
--------------------------------------------------------------------------------
        ID
----------
VALUE
--------------------------------------------------------------------------------
TITLE
--------------------------------------------------------------------------------
IMAGE
--------------------------------------------------------------------------------

CHUNK_2
         1

NAME
--------------------------------------------------------------------------------
        ID
----------
VALUE
--------------------------------------------------------------------------------
TITLE
--------------------------------------------------------------------------------
IMAGE
--------------------------------------------------------------------------------
"hello world"
Iris plot
89504E470D0A1A0A0000000D4948445200000280000001E0080600000035D1DCE400000039744558

NAME
--------------------------------------------------------------------------------
        ID
----------
VALUE
--------------------------------------------------------------------------------
TITLE
--------------------------------------------------------------------------------
IMAGE
--------------------------------------------------------------------------------
74536F667477617265004D6174706C6F746C69622076657273696F6E332E332E332C206874747073
3A2F2F6D6174706C6F746C69622E6F72672FC897B79C000000097048597300000F6100000F6101A8
3FA7690000ABB149444154789CECDD79985C65993EFEFB2C55A7BABBBA7A4D6F49670F21210B1002

NAME
--------------------------------------------------------------------------------
        ID
----------
VALUE
--------------------------------------------------------------------------------
TITLE
--------------------------------------------------------------------------------
IMAGE
--------------------------------------------------------------------------------
84C5B093804846C5AF8E4C4445470467181CD1388A0A32114401C71FA88802A31807075019092092

CHUNK_3

NAME
--------------------------------------------------------------------------------
        ID
----------
VALUE
--------------------------------------------------------------------------------
TITLE
--------------------------------------------------------------------------------
IMAGE
--------------------------------------------------------------------------------
         1
"hello world"
Iris plot

NAME
--------------------------------------------------------------------------------
        ID
----------
VALUE
--------------------------------------------------------------------------------
TITLE
--------------------------------------------------------------------------------
IMAGE
--------------------------------------------------------------------------------
89504E470D0A1A0A0000000D4948445200000280000001E0080600000035D1DCE400000039744558
74536F667477617265004D6174706C6F746C69622076657273696F6E332E332E332C206874747073
3A2F2F6D6174706C6F746C69622E6F72672FC897B79C000000097048597300000F6100000F6101A8

NAME
--------------------------------------------------------------------------------
        ID
----------
VALUE
--------------------------------------------------------------------------------
TITLE
--------------------------------------------------------------------------------
IMAGE
--------------------------------------------------------------------------------
3FA76900008C7149444154789CEDDD77945BD5D536F0E7AA774D2F9EE25EB14D316D3060209862E2
50120204B009900487040229E004028418432881242FA663E7230402015E9AF14B33C5543730B671

次の例では、サンプルのirisデータの行チャンクを予測するために、Pythonモデルlinregrをロードします。モデルは作成され、データストアpymodel (「pyqTableEvalファンクション(Autonomous Database)」の例を参照)に保存されます。

この例では、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); -- V_GLOBAL, V_OVERWRITE
END;
/

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

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

PAR_LST引数は、入力データをpandas.DataFrameとして、特殊な制御引数oml_input_type、および関数引数modelNamedatastoreNameの値とともに渡すことを指定します。

OUT_FMT引数で、JSON文字列は、構造化表の出力の列名とデータ型を指定します。

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

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

SELECT *
    FROM table(pyqRowEval(
        inp_nam => 'SAMPLE_IRIS',
        par_lst => '{"oml_input_type":"pandas.DataFrame",
                     "modelName":"linregr", "datastoreName":"pymodel"}',
        out_fmt => '{"Species":"varchar2(12)", "Petal_Length":"number", "Pred_Petal_Width":"number"}',
        row_num => 5,
        scr_name => 'linregrPredict'));

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

Species      Petal_Length   Pred_Petal_Width   
setosa                  1.2       0.0653133202 
versicolor              4.5        1.632087234 
setosa                  1.3       0.2420812759 
setosa                  1.9       0.5181904241 
setosa                  1.4       0.2162518989 
setosa                  1.4       0.1732424372 
setosa                  1.5       0.2510460971 
setosa                  1.3       0.1907951829 
versicolor              3.9       1.1999981051 
versicolor              4.2       1.4017887483 
versicolor                4       1.2332360562 
versicolor              4.8        1.765473067 
virginica               5.6       2.0095892178 
versicolor              4.7       1.5824801232 

Species      Petal_Length   Pred_Petal_Width   
virginica               5.4       2.0623088225 
versicolor              4.7       1.6524411804 
virginica               5.6       1.9919751044 
virginica               5.8       2.1206308288 
virginica               5.1       1.7983383572 
versicolor              4.4       1.3677441077 


20 rows selected. 

pyqRowEvalファンクションを起動してXML出力を返すSELECT文を実行します。スクリプトlinregrPredictの各呼出しは、SAMPLE_IRIS表の10行のデータに適用されます。XML出力はCLOBです。set long [length]をコールすると、詳細出力を取得できます。

set long 300
SELECT *
    FROM table(pyqRowEval(
        inp_nam => 'SAMPLE_IRIS',
        par_lst => '{"oml_input_type":"pandas.DataFrame",
                     "modelName":"linregr", "datastoreName":"pymodel", "oml_parallel_flag":true", "oml_service_level":"MEDIUM"}',
        out_fmt => 'XML',
        row_num => 10,
        scr_name => 'linregrPredict'));

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

NAME VALUE
       <root><pandas_dataFrame><ROW-pandas_dataFrame><Species>setosa</Species><Sepal_Length>5</Sepal_Length><Sepal_Width>3.2</Sepal_Width><Petal_Length>1.2</Petal_Length><Petal_Width>0.2</Petal_Width><Pred_Petal_Width>0.0653133201897007</Pred_Petal_Width></ROW-pandas_dataFrame><ROW-pandas_dataFrame><Species>