<jupyter_start><jupyter_text>Weight of Evidence with pandas<jupyter_code># Let's get the inverse of the target values
# to be able to calculate the negative cases

neg_y_train = pd.Series(
    np.where(y_train == 1, 0, 1),
    index=y_train.index,
)
# Let's obtain the number of observations
# where the target takes the value 1 or 0

total_pos = y_train.sum()
total_neg = neg_y_train.sum()

total_pos, total_neg
# Determine the numerator and denominator of the
# WoE formula

pos = y_train.groupby(X_train["A1"]).sum() / total_pos
neg = neg_y_train.groupby(X_train["A1"]).sum() / total_neg

pos, neg
# Calculate the WoE

woe = np.log(pos / neg)

woe
# Replace categories with the woe

X_train["A1"] = X_train["A1"].map(woe)
X_test["A1"] = X_test["A1"].map(woe)
# Inspect encoded variable

X_train["A1"].head()<jupyter_output><empty_output><jupyter_text>Weight of Evidence with Feature-engine<jupyter_code>from feature_engine.encoding import WoEEncoder
# Let's separate into training and testing sets

X_train, X_test, y_train, y_test = train_test_split(
    data.drop(labels=["target"], axis=1),  # predictors
    data["target"],  # target
    test_size=0.3,  # percentage of observations in test set
    random_state=0,  # seed to ensure reproducibility
)
# Set up the weight of evidence encoder to
# encode a few variables

woe_enc = WoEEncoder(variables=["A1", "A9", "A12"])
# Find the WoE values for each category

woe_enc.fit(X_train, y_train)
# let's inspect the variables that will be encoded

woe_enc.variables_
# the encoder stores the woe values per category per variable

woe_enc.encoder_dict_
# let's transform train and test sets

X_train_enc = woe_enc.transform(X_train)
X_test_enc = woe_enc.transform(X_test)
# Inspect the encoded data

X_train_enc.head()
# Inspect the encoded data

X_test_enc.head()<jupyter_output><empty_output><jupyter_text>Weight of Evidence with Category Encoders<jupyter_code>from category_encoders.woe import WOEEncoder
# Set up the weight of evidence encoder to
# encode a few variables

woe_enc = WOEEncoder(cols=["A1", "A9", "A12"])
# Find the WoE values for each category

woe_enc.fit(X_train, y_train)
# The WoE values are stored in the mapping attribute

# (the values are slightly different from those from
# Feature-engine because of the regularization term.
# If we set regularization=0, the values should be identical)

woe_enc.mapping
# let's transform train and test sets

X_train_enc = woe_enc.transform(X_train)
X_test_enc = woe_enc.transform(X_test)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09625246548323471, 'fraction_numerical': 0.009861932938856016, 'mean_word_length': 5.3879093198992445, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, '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': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '486468', 'license': 'MIT', 'n_tokens_mistral': 900, 'n_tokens_neox': 866, 'n_words': 263, 'path': 'ch02-categorical-encoding/Recipe-08-Weight-of-evidence.ipynb', 'repo_name': 'PacktPublishing/Python-Feature-Engineering-Cookbook-Second-Edition', 'size': '2535'}