def datasets_hyperparameters_validation(dataset_list, model, param_grid, scale=False, test_size=0.2, time_series=False, random_state=123, n_folds=5, regr=True, plot=False, plot_train=False, xvalues=None, xlabel='Datasets', title='Datasets validation', figsize=(6, 6)):
    "\n    Select the best dataset and the best combination of values for the specified hyperparameters of the specified model (i.e.\n    select the best couple dataset-combination of hyperparameters values).\n\n    For each dataset in `dataset_list`, all the possible combinations of the hyperparameters values for `model` (specified\n    with `param_grid`) are tested.\n    In other words, on each dataset the tuning of the specified hyperparameters is performed in an exhaustive way: in fact,\n    on each dataset, the function `hyperparameters_validation` is applied. (See `hyperparameters_validation`).\n    In the end, the best couple dataset-combination of hyperparameters values is selected.\n\n    Despite the fact that a couple dataset-combination of hyperparameters values is selected, the main viewpoint is focused\n    with respect to the datasets. It's a validation focused on the datasets.\n    In fact, first of all, for each dataset the hyperparameters tuning is performed: in this way the best combination of\n    values is selected and its relative score is associated with the dataset (i.e. it's the score of the dataset). (In other\n    words, on each dataset the function `hyperparameters_validation` is applied). Finally, after that, the best dataset is\n    selected. It's a two-levels selection.\n\n    This selection is made using the validation score (i.e. the best couple dataset-combination of hyperparameters values, is\n    the one with best validation score).\n    The validation score is computed by splitting each dataset into the training-test sets and then by applying the cross\n    validation on the training set.\n    Additionally, the training and test scores are also computed.\n\n    Optionally, the validation scores of the datasets can be plotted, making a graphical visualization of the dataset\n    selection.\n\n    Parameters\n    ----------\n    dataset_list: list\n        List of couple, where each couple is a dataset.\n            - The first element is X, the two-dimensional np.array containing the explanatory features of the dataset.\n            - The second element is y, the mono dimensional np.array containing the response feature of the dataset.\n    model: sklearn.base.BaseEstimator\n        Model which has the specified hyperparameters.\n    param_grid: dict\n        Dictionary which has as keys the names of the specified hyperparameters and as values the associated list of\n        values to test.\n    scale: bool\n        Indicates whether to scale or not the features in 'X' (for all the datasets).\n        (The scaling is performed using the sklearn MinMaxScaler).\n    test_size: float\n        Decimal number between 0 and 1, which indicates the proportion of the test set (for each dataset).\n    time_series: bool\n        Indicates if the given datasets are time series datasets (i.e. datasets indexed by days).\n        (This affects the computing of the validation score).\n    random_state: int\n        Used in the training-test splitting of the datasets.\n    n_folds: int\n        Indicates how many folds are made in order to compute the k-fold cross validation.\n        (It's used only if `time_series` is False).\n    regr: bool\n        Indicates if it's either a regression or a classification problem.\n    plot: bool\n        Indicates whether to plot or not the validation score values of the datasets.\n    plot_train: bool\n        Indicates whether to plot also the training scores.\n        (It's considered only if `plot` is True).\n    xvalues: list (in general, iterable)\n        Values that have to be put in the x axis of the plot.\n    xlabel: str\n        Label of the x axis of the plot.\n    title: str\n        Title of the plot.\n    figsize: tuple\n        Two dimensions of the plot.\n\n    Returns\n    ----------\n    datasets_train_val_score: np.array\n        Two dimensional np.array, containing two columns: the first contains the training scores, the second the validation\n        scores.\n        It has as many rows as the number of datasets to test, i.e. as the number of elements in `dataset_list`.\n    datasets_best_params: list\n        List which has as many elements as the number of the datasets (i.e. as the number of elements in `dataset_list`). For\n        each dataset, it contains the best combination of hyperparameters values on that dataset.\n        Each combination is represented as a dictionary, with keys the hyperparameters names and values the associated\n        values.\n    best_index: int\n        Index of `dataset_list` that indicates which is the best dataset.\n    test_score: float\n        Test score associated with the best couple dataset-combination of hyperparameters values.\n    ax: matplotlib.axes.Axes\n        The matplotlib Axes where the plot has been made.\n\n    See also\n    ----------\n    hyperparameters_validation:\n        select the best combination of values for the specified hyperparameters of the specified model on the given dataset.\n\n    Notes\n    ----------\n    - If `regr` is True, the validation scores are errors (MSE, i.e. Mean Squared Errors): this means that the best\n      couple dataset-combination of hyperparameters values is the one associated with the minimum validation score.\n      Otherwise, the validation scores are accuracies: this means that the best couple is the one associated with the\n      maximum validation score.\n    - If `time_series` is False, the training-test splitting of each dataset is made randomly. In addition, the cross\n      validation strategy performed is the classic k-fold cross validation: the number of folds is specified by `n_folds`.\n      Otherwise, if `time_series` is True, the training-test sets are simply obtained by splitting each dataset into two\n      contiguous parts. In addition, the cross validation strategy performed is the sklearn TimeSeriesSplit.\n    "
    datasets_train_val_score = []
    datasets_best_params = []
    datasets_test_score = []
    for (X, y) in dataset_list:
        (params, train_val_scores, best_index, test_score) = hyperparameters_validation(X, y, model, param_grid, scale=scale, test_size=test_size, time_series=time_series, random_state=random_state, n_folds=n_folds, regr=regr)
        datasets_train_val_score.append(tuple(train_val_scores[best_index, :]))
        datasets_best_params.append(params[best_index])
        datasets_test_score.append(test_score)
    datasets_train_val_score = np.array(datasets_train_val_score)
    if regr:
        best_index = np.argmin(datasets_train_val_score, axis=0)[1]
    else:
        best_index = np.argmax(datasets_train_val_score, axis=0)[1]
    test_score = datasets_test_score[best_index]
    ax = None
    if plot:
        if (not xvalues):
            xvalues = range(len(dataset_list))
        ax = _plot_TrainVal_values(xvalues, datasets_train_val_score, plot_train, xlabel, title, figsize, bar=True)
    return (datasets_train_val_score, datasets_best_params, best_index, test_score, ax)
Select the best dataset and the best combination of values for the specified hyperparameters of the specified model (i.e.
select the best couple dataset-combination of hyperparameters values).

For each dataset in `dataset_list`, all the possible combinations of the hyperparameters values for `model` (specified
with `param_grid`) are tested.
In other words, on each dataset the tuning of the specified hyperparameters is performed in an exhaustive way: in fact,
on each dataset, the function `hyperparameters_validation` is applied. (See `hyperparameters_validation`).
In the end, the best couple dataset-combination of hyperparameters values is selected.

Despite the fact that a couple dataset-combination of hyperparameters values is selected, the main viewpoint is focused
with respect to the datasets. It's a validation focused on the datasets.
In fact, first of all, for each dataset the hyperparameters tuning is performed: in this way the best combination of
values is selected and its relative score is associated with the dataset (i.e. it's the score of the dataset). (In other
words, on each dataset the function `hyperparameters_validation` is applied). Finally, after that, the best dataset is
selected. It's a two-levels selection.

This selection is made using the validation score (i.e. the best couple dataset-combination of hyperparameters values, is
the one with best validation score).
The validation score is computed by splitting each dataset into the training-test sets and then by applying the cross
validation on the training set.
Additionally, the training and test scores are also computed.

Optionally, the validation scores of the datasets can be plotted, making a graphical visualization of the dataset
selection.

Parameters
----------
dataset_list: list
    List of couple, where each couple is a dataset.
        - The first element is X, the two-dimensional np.array containing the explanatory features of the dataset.
        - The second element is y, the mono dimensional np.array containing the response feature of the dataset.
model: sklearn.base.BaseEstimator
    Model which has the specified hyperparameters.
param_grid: dict
    Dictionary which has as keys the names of the specified hyperparameters and as values the associated list of
    values to test.
scale: bool
    Indicates whether to scale or not the features in 'X' (for all the datasets).
    (The scaling is performed using the sklearn MinMaxScaler).
test_size: float
    Decimal number between 0 and 1, which indicates the proportion of the test set (for each dataset).
time_series: bool
    Indicates if the given datasets are time series datasets (i.e. datasets indexed by days).
    (This affects the computing of the validation score).
random_state: int
    Used in the training-test splitting of the datasets.
n_folds: int
    Indicates how many folds are made in order to compute the k-fold cross validation.
    (It's used only if `time_series` is False).
regr: bool
    Indicates if it's either a regression or a classification problem.
plot: bool
    Indicates whether to plot or not the validation score values of the datasets.
plot_train: bool
    Indicates whether to plot also the training scores.
    (It's considered only if `plot` is True).
xvalues: list (in general, iterable)
    Values that have to be put in the x axis of the plot.
xlabel: str
    Label of the x axis of the plot.
title: str
    Title of the plot.
figsize: tuple
    Two dimensions of the plot.

Returns
----------
datasets_train_val_score: np.array
    Two dimensional np.array, containing two columns: the first contains the training scores, the second the validation
    scores.
    It has as many rows as the number of datasets to test, i.e. as the number of elements in `dataset_list`.
datasets_best_params: list
    List which has as many elements as the number of the datasets (i.e. as the number of elements in `dataset_list`). For
    each dataset, it contains the best combination of hyperparameters values on that dataset.
    Each combination is represented as a dictionary, with keys the hyperparameters names and values the associated
    values.
best_index: int
    Index of `dataset_list` that indicates which is the best dataset.
test_score: float
    Test score associated with the best couple dataset-combination of hyperparameters values.
ax: matplotlib.axes.Axes
    The matplotlib Axes where the plot has been made.

See also
----------
hyperparameters_validation:
    select the best combination of values for the specified hyperparameters of the specified model on the given dataset.

Notes
----------
- If `regr` is True, the validation scores are errors (MSE, i.e. Mean Squared Errors): this means that the best
  couple dataset-combination of hyperparameters values is the one associated with the minimum validation score.
  Otherwise, the validation scores are accuracies: this means that the best couple is the one associated with the
  maximum validation score.
- If `time_series` is False, the training-test splitting of each dataset is made randomly. In addition, the cross
  validation strategy performed is the classic k-fold cross validation: the number of folds is specified by `n_folds`.
  Otherwise, if `time_series` is True, the training-test sets are simply obtained by splitting each dataset into two
  contiguous parts. In addition, the cross validation strategy performed is the sklearn TimeSeriesSplit.
def datasets_hyperparameters_validation(dataset_list, model, param_grid, scale=False, test_size=0.2, time_series=False, random_state=123, n_folds=5, regr=True, plot=False, plot_train=False, xvalues=None, xlabel='Datasets', title='Datasets validation', figsize=(6, 6)):
    "\n    Select the best dataset and the best combination of values for the specified hyperparameters of the specified model (i.e.\n    select the best couple dataset-combination of hyperparameters values).\n\n    For each dataset in `dataset_list`, all the possible combinations of the hyperparameters values for `model` (specified\n    with `param_grid`) are tested.\n    In other words, on each dataset the tuning of the specified hyperparameters is performed in an exhaustive way: in fact,\n    on each dataset, the function `hyperparameters_validation` is applied. (See `hyperparameters_validation`).\n    In the end, the best couple dataset-combination of hyperparameters values is selected.\n\n    Despite the fact that a couple dataset-combination of hyperparameters values is selected, the main viewpoint is focused\n    with respect to the datasets. It's a validation focused on the datasets.\n    In fact, first of all, for each dataset the hyperparameters tuning is performed: in this way the best combination of\n    values is selected and its relative score is associated with the dataset (i.e. it's the score of the dataset). (In other\n    words, on each dataset the function `hyperparameters_validation` is applied). Finally, after that, the best dataset is\n    selected. It's a two-levels selection.\n\n    This selection is made using the validation score (i.e. the best couple dataset-combination of hyperparameters values, is\n    the one with best validation score).\n    The validation score is computed by splitting each dataset into the training-test sets and then by applying the cross\n    validation on the training set.\n    Additionally, the training and test scores are also computed.\n\n    Optionally, the validation scores of the datasets can be plotted, making a graphical visualization of the dataset\n    selection.\n\n    Parameters\n    ----------\n    dataset_list: list\n        List of couple, where each couple is a dataset.\n            - The first element is X, the two-dimensional np.array containing the explanatory features of the dataset.\n            - The second element is y, the mono dimensional np.array containing the response feature of the dataset.\n    model: sklearn.base.BaseEstimator\n        Model which has the specified hyperparameters.\n    param_grid: dict\n        Dictionary which has as keys the names of the specified hyperparameters and as values the associated list of\n        values to test.\n    scale: bool\n        Indicates whether to scale or not the features in 'X' (for all the datasets).\n        (The scaling is performed using the sklearn MinMaxScaler).\n    test_size: float\n        Decimal number between 0 and 1, which indicates the proportion of the test set (for each dataset).\n    time_series: bool\n        Indicates if the given datasets are time series datasets (i.e. datasets indexed by days).\n        (This affects the computing of the validation score).\n    random_state: int\n        Used in the training-test splitting of the datasets.\n    n_folds: int\n        Indicates how many folds are made in order to compute the k-fold cross validation.\n        (It's used only if `time_series` is False).\n    regr: bool\n        Indicates if it's either a regression or a classification problem.\n    plot: bool\n        Indicates whether to plot or not the validation score values of the datasets.\n    plot_train: bool\n        Indicates whether to plot also the training scores.\n        (It's considered only if `plot` is True).\n    xvalues: list (in general, iterable)\n        Values that have to be put in the x axis of the plot.\n    xlabel: str\n        Label of the x axis of the plot.\n    title: str\n        Title of the plot.\n    figsize: tuple\n        Two dimensions of the plot.\n\n    Returns\n    ----------\n    datasets_train_val_score: np.array\n        Two dimensional np.array, containing two columns: the first contains the training scores, the second the validation\n        scores.\n        It has as many rows as the number of datasets to test, i.e. as the number of elements in `dataset_list`.\n    datasets_best_params: list\n        List which has as many elements as the number of the datasets (i.e. as the number of elements in `dataset_list`). For\n        each dataset, it contains the best combination of hyperparameters values on that dataset.\n        Each combination is represented as a dictionary, with keys the hyperparameters names and values the associated\n        values.\n    best_index: int\n        Index of `dataset_list` that indicates which is the best dataset.\n    test_score: float\n        Test score associated with the best couple dataset-combination of hyperparameters values.\n    ax: matplotlib.axes.Axes\n        The matplotlib Axes where the plot has been made.\n\n    See also\n    ----------\n    hyperparameters_validation:\n        select the best combination of values for the specified hyperparameters of the specified model on the given dataset.\n\n    Notes\n    ----------\n    - If `regr` is True, the validation scores are errors (MSE, i.e. Mean Squared Errors): this means that the best\n      couple dataset-combination of hyperparameters values is the one associated with the minimum validation score.\n      Otherwise, the validation scores are accuracies: this means that the best couple is the one associated with the\n      maximum validation score.\n    - If `time_series` is False, the training-test splitting of each dataset is made randomly. In addition, the cross\n      validation strategy performed is the classic k-fold cross validation: the number of folds is specified by `n_folds`.\n      Otherwise, if `time_series` is True, the training-test sets are simply obtained by splitting each dataset into two\n      contiguous parts. In addition, the cross validation strategy performed is the sklearn TimeSeriesSplit.\n    "
    datasets_train_val_score = []
    datasets_best_params = []
    datasets_test_score = []
    for (X, y) in dataset_list:
        (params, train_val_scores, best_index, test_score) = hyperparameters_validation(X, y, model, param_grid, scale=scale, test_size=test_size, time_series=time_series, random_state=random_state, n_folds=n_folds, regr=regr)
        datasets_train_val_score.append(tuple(train_val_scores[best_index, :]))
        datasets_best_params.append(params[best_index])
        datasets_test_score.append(test_score)
    datasets_train_val_score = np.array(datasets_train_val_score)
    if regr:
        best_index = np.argmin(datasets_train_val_score, axis=0)[1]
    else:
        best_index = np.argmax(datasets_train_val_score, axis=0)[1]
    test_score = datasets_test_score[best_index]
    ax = None
    if plot:
        if (not xvalues):
            xvalues = range(len(dataset_list))
        ax = _plot_TrainVal_values(xvalues, datasets_train_val_score, plot_train, xlabel, title, figsize, bar=True)
    return (datasets_train_val_score, datasets_best_params, best_index, test_score, ax)