Exemple:
CREATE OR REPLACE FUNCTION pybool_func(a int) RETURNS boolean
AS $$
    if (a > 0):
        return True
    else:
        return False
$$ LANGUAGE 'plpythonu';

SELECT pybool_func(-1);

 pybool_func
-------------
 f
(1 row)

CREATE OR REPLACE FUNCTION pybool_func(a int) RETURNS boolean AS $$
# container: plc_python3_shared
    if (a > 0):
        return True
    else:
        return False
$$ LANGUAGE plcontainer;

SELECT pybool_func(-1);

 pybool_func
-------------
 f
(1 row)

%%sql
CREATE EXTERNAL WEB TABLE abalone_external(
    sex text 
    , length float8
    , diameter float8
    , height float8
    , whole_weight float8
    , shucked_weight float8
    , viscera_weight float8
    , shell_weight float8
    , rings integer -- target variable faire prédire
) location('http://archive.ics.uci.edu/ml/machine-learning-databases/abalone/abalone.data') 
format 'CSV' 
(null as '?');

%%sql
CREATE TABLE abalone AS (
    SELECT ROW_NUMBER() OVER() AS id, *
    FROM abalone_external 
) DISTRIBUTED BY (sex);

%%sql
SELECT * FROM abalone ORDER BY id LIMIT 5;

%%sql
SELECT gp_segment_id, sex, COUNT(*) 
FROM abalone
GROUP BY 1, sex
ORDER BY gp_segment_id;

%%sql
SELECT madlib.train_test_split(
    'abalone'             -- source table
    , 'abalone_split'     -- output table
    , 0.8                 -- proportion pour entraînement
    , 0.2                 -- proportion pour test
    , 'sex'               -- définition des strates
    , NULL                -- colonnes de sortie
    , FALSE               -- échantillonnage avec remplaçants
    , FALSE);             -- tables de sortie séparées

%%sql
SELECT * FROM abalone_split ORDER BY id LIMIT 5;

%%sql
CREATE TYPE linreg_type AS (
    col_nm text[]
    , coef float8[]
    , intercept float8
    , serialized_linreg_model bytea
    , created_dt text
);

%%sql
CREATE OR REPLACE FUNCTION linreg_func(
    length float8[]
    , shucked_weight float8[]
    , rings integer[]
) RETURNS linreg_type 
AS $$

    from sklearn.linear_model import LinearRegression
    import numpy as np
    
    X = np.array([length, shucked_weight]).T
    y = np.array([rings]).T
    
    # Régression linéaire avec longueurs et poids
    linreg_fit = LinearRegression().fit(X, y)
    linreg_coef = linreg_fit.coef_
    linreg_intercept = linreg_fit.intercept_
    
    # Serialization du modèle entrainé
    import pickle
    serialized_linreg_model = pickle.dumps(linreg_fit, protocol=2) # protocol = 3 pour Python 3.x
    
    return {
        'col_nm': ['length', 'shucked_weight'],
        'coef': linreg_coef[0],
        'intercept': linreg_intercept[0],
        'serialized_linreg_model': serialized_linreg_model,
        'created_dt': str(datetime.datetime.now())}
    
$$ LANGUAGE plPythonu;

%%sql
CREATE TABLE linreg_fitted AS (
    SELECT
        a.sex
        , (linreg_func(
            a.length_agg
            , a.shucked_weight_agg
            , a.rings_agg)
        ).*
    FROM (
        SELECT
            sex
            , ARRAY_AGG(length) AS length_agg
            , ARRAY_AGG(shucked_weight) AS shucked_weight_agg
            , ARRAY_AGG(rings) AS rings_agg
        FROM abalone_split
        WHERE split = 1
        GROUP BY sex
    ) a
) DISTRIBUTED BY (sex);

%%sql
SELECT sex, col_nm, coef, intercept, created_dt FROM linreg_fitted;

%%sql
CREATE FUNCTION linreg_pred_func(
    serialized_model bytea
    , features float8[]
) RETURNS SETOF float8
AS $$
    
    # Désérialiser le modèle sérialisé
    import six
    pickle = six.moves.cPickle
    model = pickle.loads(serialized_model)
    
    # Prédire la variable cible
    y_pred = model.predict([features])
    
    return y_pred[0]

$$ LANGUAGE 'plpythonu';

%%sql
CREATE TABLE linreg_pred AS (
    SELECT 
        test.id
        , test.sex
        , test.rings
        , linreg_pred_func(
            model.serialized_linreg_model   -- bytea
            , ARRAY[length, shucked_weight] -- array
        ) AS y_pred
    FROM 
        (SELECT * FROM abalone_split WHERE split=0) AS test
        , linreg_fitted AS model
    WHERE test.sex = model.sex
) DISTRIBUTED BY (sex);

%%sql
SELECT * FROM linreg_pred WHERE sex='I' ORDER BY id LIMIT 5;

CREATE FUNCTION linreg_pred_dot_func(
    coef float8[]
    , intercept float8
    , features float8[]
) RETURNS SETOF float8
AS $$    import numpy as np
    
    # Prédire la variable cible
    y_pred = np.dot(coef, np.array([features]).T) + intercept
    
    return y_pred

$$ LANGUAGE 'plpythonu';

%%sql
CREATE TYPE linreg_eval_type AS (
    mae float8
    , mape float8
    , mse float8
    , r2_score float8
);

%%sql
CREATE FUNCTION linreg_eval(
    y_actual float8[]
    , y_pred float8[]
) RETURNS linreg_eval_type
AS $$    from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
    import numpy as np
    
    mae = mean_absolute_error(y_actual, y_pred)
    mse = mean_squared_error(y_actual, y_pred)
    r2_score = r2_score(y_actual, y_pred)
    
    y_pred_f = np.array(y_pred, dtype=float)
    mape = 100 * sum(abs(y_actual - y_pred_f)/y_actual) / len(y_actual)
    
    #eval_score = [mae, mape, mse, r2_score]
    
    return {
        'mae': mae, 
        'mape': mape, 
        'mse': mse, 
        'r2_score': r2_score
    }

$$ LANGUAGE 'plpythonu';

%%sql
SELECT 
    sex
    , (linreg_eval(rings_agg, y_pred_agg)).*
FROM (
    SELECT 
        sex
        , ARRAY_AGG(rings) AS rings_agg
        , ARRAY_AGG(y_pred) AS y_pred_agg
    FROM linreg_pred
    GROUP BY sex
) a