<jupyter_start><jupyter_text>Discretization using Decision Trees<jupyter_code># example: build Regression tree using MedInc to predict house price

tree_model = DecisionTreeRegressor(max_depth=3, random_state=0)

tree_model.fit(X_train["MedInc"].to_frame(), y_train)
# create features with output of decision tree

X_train["MedInc_tree"] = tree_model.predict(X_train["MedInc"].to_frame())
X_test["MedInc_tree"] = tree_model.predict(X_test["MedInc"].to_frame())
# let's explore the number of unique values in
# our "discrete" variable

X_test["MedInc_tree"].nunique()
# let's explore the unique values

X_test["MedInc_tree"].unique()
# monotonic relationship with target: test set

y_test.groupby(X_test["MedInc_tree"]).mean().plot()
plt.title("Monotonic relationship between discretised MedInc and target")
plt.ylabel("Median Price")
# plot number of observations per "bin"

X_test.groupby(["MedInc_tree"])["MedInc"].count().plot.bar()
# let's analyize the decision tree

fig = plt.figure(figsize=(20, 6))
plot_tree(tree_model, fontsize=10, proportion=True)
plt.show()<jupyter_output><empty_output><jupyter_text>Decision tree discretization with Feature-engine<jupyter_code>from feature_engine.discretisation import DecisionTreeDiscretiser
# let's separate into training and testing set

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.3,
    random_state=0,
)
variables = list(X.columns)[:-2]

variables
# set up the decision tree discretiser indicating:

# cross-validation fold (cv)
# the metric to evaluate model performance (scoring)
# the variables we want to discretise (variables)
# whether it is a target for regression or classification
# and the grid with hyperparameters to optimize the decision tree

treeDisc = DecisionTreeDiscretiser(
    cv=3,
    scoring="neg_mean_squared_error",
    variables=variables,
    regression=True,
    param_grid={"max_depth": [1, 2, 3], "min_samples_leaf": [10, 20, 50]},
)

treeDisc.fit(X_train, y_train)
# we can inspect the best parameters found for the tree for MedInc

treeDisc.binner_dict_["MedInc"].best_params_
# the scores for the tree here

treeDisc.scores_dict_["MedInc"]
# let's transform the data

train_t = treeDisc.transform(X_train)
test_t = treeDisc.transform(X_test)
# Let's plot 3 variables:

plt.figure(figsize=(6, 12), constrained_layout=True)

for i in range(3):

    # location in figure
    ax = plt.subplot(3, 1, i + 1)

    # variable to plot
    var = variables[i]

    # determine proportion of observations per bin
    t1 = train_t[var].value_counts(normalize=True)
    t2 = test_t[var].value_counts(normalize=True)

    # concatenate proportions
    tmp = pd.concat([t1, t2], axis=1)
    tmp.columns = ["train", "test"]

    # order the intervals
    tmp.sort_index(inplace=True)

    tmp.plot.bar(ax=ax)
    plt.xticks(rotation=45)
    plt.ylabel("Observations per bin")

    # add variable name as title
    ax.set_title(var)

plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11372022811137203, 'fraction_numerical': 0.012076484401207649, 'mean_word_length': 5.3312101910828025, 'pattern_counts': {'":': 2, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '579021', 'license': 'MIT', 'n_tokens_mistral': 1051, 'n_tokens_neox': 982, 'n_words': 255, 'path': 'ch04-discretization/Recipe-6-Discretisation-with-decision-trees.ipynb', 'repo_name': 'PacktPublishing/Python-Feature-Engineering-Cookbook-Second-Edition', 'size': '2981'}