12.5.5 行セットに対するユーザー定義Python関数の実行
oml.row_apply
関数を使用して、データを行セットにチャンク化し、各チャンクに対してユーザー定義Python関数を実行します。
oml.row_apply
関数は、data
引数で指定されたoml.DataFrame
を最初の引数としてユーザー定義のfunc
Python関数に渡します。rows
引数では、各チャンクに割り当てるoml.DataFrame
の最大行数を指定します。最後の行チャンクの行は、指定した数より少なくなることがあります。
oml.row_apply
関数は、データベースによって生成されたPythonエンジンでPython関数を実行します。この関数では、1つ以上のPythonエンジンが同じPython関数を異なるデータ・チャンクに対して実行するデータ・パラレル実行を使用できます。
この関数の構文は次のとおりです。
oml.row_apply(data, func, func_owner=None, rows=1, parallel=None, graphics=False, **kwargs)
data
引数は、func
関数が操作するデータを含むoml.DataFrame
です。
func
引数は、実行する関数です。これには次のいずれかを指定できます。
-
Python関数
-
OML4Pyスクリプト・リポジトリ内のユーザー定義Python関数の名前を表す文字列
- Python関数を定義する文字列
-
oml.script.load
関数によって返されるoml.script.script.Callable
オブジェクト
オプションのfunc_owner
引数は文字列またはNone
(デフォルト)で、引数func
が登録済ユーザー定義Python関数名の場合に、登録済ユーザー定義Python関数の所有者を指定します。
rows
引数は、各チャンクに含める最大行数を指定するint
です。
parallel
引数は、Embedded Python Executionジョブで使用する推奨並列度を指定するブール値、int
またはNone
(デフォルト)です。次の値のいずれかを指定できます。
-
特定の並列度では、1以上の正の整数
-
並列度なしの場合は
False
、None
または0
-
デフォルトのデータ並列度の場合は
True
graphics
引数は、イメージを検索するかどうかを指定するブール値です。デフォルト値はTrue
です。
**kwargs
パラメータを使用すると、func
関数に追加の引数を渡すことができます。oml_
で始まる特殊な制御引数は、func
で指定された関数に渡されるのではなく、関数の実行前または実行後の動作を制御します。
oml.row_apply
関数は、pandas.DataFrame
、またはoml.embed.data_image._DataImage
オブジェクトのリストを返します。ユーザー定義Python関数でイメージがレンダリングされない場合、oml.row_apply
はpandas.DataFrame
を返します。それ以外の場合は、oml.embed.data_image._DataImage
オブジェクトのリストを返します。
例12-9 oml.row_apply関数の使用
この例では、irisデータセットを使用してx
変数とy
変数を作成します。その後、永続データベース表IRISとoml.DataFrame
オブジェクトoml_iris
を表のプロキシとして作成します。
この例では、irisデータに基づいて回帰モデルを構築します。入力データのSepal_Length、Sepal_WidthおよびPetal_Length列に基づいてPetal_Width値を予測する関数を定義します。次に、返すオブジェクトとしてSpecies列、Petal_Width列および予測されたPetal_Widthを連結します。最後に、oml.row_apply
関数をコールして、入力データの4行のチャンクそれぞれに対してmake_pred()
関数を適用します。
import oml
import pandas as pd
from sklearn import datasets
from sklearn import linear_model
# Load the iris data set and create a pandas.DataFrame for it.
iris = datasets.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'])
# Drop the IRIS database table if it exists.
try:
oml.drop('IRIS')
except:
pass
# Create the IRIS database table and the proxy object for the table.
oml_iris = oml.create(pd.concat([x, y], axis=1), table = 'IRIS')
# Build a regression model to predict Petal_Width using in-memory
# data.
iris = oml_iris.pull()
regr = linear_model.LinearRegression()
regr.fit(iris[['Sepal_Length', 'Sepal_Width', 'Petal_Length']],
iris[['Petal_Width']])
regr.coef_
# Define a Python function.
def make_pred(dat, regr):
import pandas as pd
import numpy as np
pred = regr.predict(dat[['Sepal_Length',
'Sepal_Width',
'Petal_Length']])
return pd.concat([dat[['Species', 'Petal_Width']],
pd.DataFrame(pred,
columns=['Pred_Petal_Width'])],
axis=1)
input_data = oml_iris.split(ratio=(0.9, 0.1), strata_cols='Species')[1]
input_data.crosstab(index = 'Species').sort_values('Species')
res = oml.row_apply(input_data, rows=4, func=make_pred,
regr=regr, parallel=2)
type(res)
res
この例のリスト
>>> import oml
>>> import pandas as pd
>>> from sklearn import datasets
>>> from sklearn import linear_model
>>>
>>> # Load the iris data set and create a pandas.DataFrame for it.
... iris = datasets.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'])
>>>
>>> # Drop the IRIS database table if it exists.
... try:
... oml.drop('IRIS')
... except:
... pass
>>>
>>> # Create the IRIS database table and the proxy object for the table.
>>> oml_iris = oml.create(pd.concat([x, y], axis=1), table = 'IRIS')
>>>
>>> # Build a regression model to predict Petal_Width using in-memory
... # data.
... iris = oml_iris.pull()
>>> regr = linear_model.LinearRegression()
>>> regr.fit(iris[['Sepal_Length', 'Sepal_Width', 'Petal_Length']],
... iris[['Petal_Width']])
LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=False)
>>> regr.coef_
array([[-0.20726607, 0.22282854, 0.52408311]])
>>>
>>> # Define a Python function.
... def make_pred(dat, regr):
... import pandas as pd
... import numpy as np
... pred = regr.predict(dat[['Sepal_Length',
... 'Sepal_Width',
... 'Petal_Length']])
... return pd.concat([dat[['Species', 'Petal_Width']],
... pd.DataFrame(pred,
... columns=['Pred_Petal_Width'])],
... axis=1)
>>>
>>> input_data = oml_iris.split(ratio=(0.9, 0.1), strata_cols='Species')[1]
>>> input_data.crosstab(index = 'Species').sort_values('Species')
SPECIES count
0 setosa 7
1 versicolor 8
2 virginica 4
>>> res = oml.row_apply(input_data, rows=4, func=make_pred, regr=regr,
... columns=['Species',
... 'Petal_Width',
... 'Pred_Petal_Width']))
>>> res = oml.row_apply(input_data, rows=4, func=make_pred,
... regr=regr, parallel=2)
>>> type(res)
<class 'pandas.core.frame.DataFrame'>
>>> res
Species Petal_Width Pred_Petal_Width
0 setosa 0.4 0.344846
1 setosa 0.3 0.335509
2 setosa 0.2 0.294117
3 setosa 0.2 0.220982
4 setosa 0.2 0.080937
5 versicolor 1.5 1.504615
6 versicolor 1.3 1.560570
7 versicolor 1.0 1.008352
8 versicolor 1.3 1.131905
9 versicolor 1.3 1.215622
10 versicolor 1.3 1.272388
11 virginica 1.8 1.623561
12 virginica 1.8 1.878132