<commit_before>import numpy as np
from lifetimes.utils import coalesce

__all__ = [
    'plot_period_transactions',
    'plot_calibration_purchases_vs_holdout_purchases',
    'plot_frequency_recency_matrix',
    'plot_expected_repeat_purchases',
    'plot_probability_alive_matrix',
]


def plot_period_transactions(model, **kwargs):
    from matplotlib import pyplot as plt

    bins = kwargs.pop('bins', range(9))
    labels = kwargs.pop('label', ['Actual', 'Model'])

    n = model.data.shape[0]
    simulated_data = model.generate_new_data(size=n)

    ax = plt.hist(np.c_[model.data['frequency'].values, simulated_data['frequency'].values],
                  bins=bins, label=labels)
    plt.legend()
    plt.xticks(np.arange(len(bins))[:-1] + 0.5, bins[:-1])
    plt.title('Frequency of Repeat Transactions')
    plt.ylabel('Customers')
    plt.xlabel('Number of Calibration Period Transactions')
    return ax


def plot_calibration_purchases_vs_holdout_purchases(model, calibration_holdout_matrix, n=7):
    """
    This currently relies too much on the lifetimes.util calibration_and_holdout_data function.

    """
    from matplotlib import pyplot as plt

    summary = calibration_holdout_matrix.copy()
    T = summary.iloc[0]['duration_holdout']

    summary['model'] = summary.apply(lambda r: model.conditional_expected_number_of_purchases_up_to_time(T, r['frequency_cal'], r['recency_cal'], r['T_cal']), axis=1)

    ax = summary.groupby('frequency_cal')[['frequency_holdout', 'model']].mean().ix[:n].plot()

    plt.title('Actual Purchases in Holdout Period vs Predicted Purchases')
    plt.xlabel('Puchases in Calibration Period')
    plt.ylabel('Average of Purchases in Holdout Period')
    plt.legend()

    return ax


def plot_frequency_recency_matrix(model, max_x=None, max_t=None, **kwargs):
    """
    Plot a figure of expected transactions in one unit of time by a customer's 
    frequency and recency.

    Parameters:
        model: a fitted lifetimes model.
        max_x: the maximum frequency to plot. Default is max observed frequency.
        max_t: the maximum recency to plot. This also determines the age of the customer.
            Defaul to max observed age. 
        kwargs: passed into the matplotlib.imshow command.

    """
    from matplotlib import pyplot as plt

    if max_x is None:
        max_x = int(model.data['frequency'].max())

    if max_t is None:
        max_t = int(model.data['T'].max())

    t = 1  # one unit of time
    Z = np.zeros((max_t+1, max_x+1))
    for i, t_x in enumerate(np.arange(max_t+1)):<commit_msg>added more ways to visualize performance on observation period<commit_after>import numpy as np
from lifetimes.utils import coalesce

__all__ = [
    'plot_period_transactions',
    'plot_calibration_purchases_vs_holdout_purchases',
    'plot_frequency_recency_matrix',
    'plot_expected_repeat_purchases',
    'plot_probability_alive_matrix',
]


def plot_period_transactions(model, **kwargs):
    from matplotlib import pyplot as plt

    bins = kwargs.pop('bins', range(9))
    labels = kwargs.pop('label', ['Actual', 'Model'])

    n = model.data.shape[0]
    simulated_data = model.generate_new_data(size=n)

    ax = plt.hist(np.c_[model.data['frequency'].values, simulated_data['frequency'].values],
                  bins=bins, label=labels)
    plt.legend()
    plt.xticks(np.arange(len(bins))[:-1] + 0.5, bins[:-1])
    plt.title('Frequency of Repeat Transactions')
    plt.ylabel('Customers')
    plt.xlabel('Number of Calibration Period Transactions')
    return ax


def plot_calibration_purchases_vs_holdout_purchases(model, calibration_holdout_matrix, kind="frequency_cal", n=7, **kwargs):
    """
    This currently relies too much on the lifetimes.util calibration_and_holdout_data function.

    Parameters:
        model: a fitted lifetimes model
        calibration_holdout_matrix: dataframe from calibration_and_holdout_data function
        kind: x-axis :"frequency_cal". Purchases in calibration period,
                      "recency_cal". Age of customer at last purchase,
                      "T_cal". Age of customer at the end of calibration period,
                      "time_since_last_purchase". Time since user made last purchase
        n: number of ticks on the x axis

    """
    from matplotlib import pyplot as plt

    x_labels = {
        "frequency_cal": "Purchases in calibration period",
        "recency_cal": "Age of customer at last purchase",
        "T_cal": "Age of customer at the end of calibration period",
        "time_since_last_purchase": "Time since user made last purchase"
    }
    summary = calibration_holdout_matrix.copy()
    duration_holdout = summary.iloc[0]['duration_holdout']

    summary['model_predictions'] = summary.apply(lambda r: model.conditional_expected_number_of_purchases_up_to_time(duration_holdout, r['frequency_cal'], r['recency_cal'], r['T_cal']), axis=1)

    if kind == "time_since_last_purchase":
        summary["time_since_last_purchase"] = summary["T_cal"] - summary["recency_cal"]
        ax = summary.groupby(["time_since_last_purchase"])[['frequency_holdout', 'model_predictions']].mean().ix[:n].plot(**kwargs)
    else:
        ax = summary.groupby(kind)[['frequency_holdout', 'model_predictions']].mean().ix[:n].plot(**kwargs)

    plt.title('Actual Purchases in Holdout Period vs Predicted Purchases')
    plt.xlabel(x_labels[kind])
    plt.ylabel('Average of Purchases in Holdout Period')
    plt.legend()

    return ax


def plot_frequency_recency_matrix(model, max_x=None, max_t=None, **kwargs):
    """
    Plot a figure of expected transactions in one unit of time by a customer's 
    frequency and recency.

    Parameters:
        model: a fitted lifetimes model.
        max_x: the maximum frequency to plot. Default is max observed frequency.
        max_t: the maximum recency to plot. This also determines the age of the customer.
            Default to max observed age.
        kwargs: passed into the matplotlib.imshow command.

    """
    from matplotlib import pyplot as plt

    if max_x is None:
        max_x = int(model.data['frequency'].max())

    if max_t is None:
        max_t = int(model.data['T'].max())

    t = 1  # one unit of time
    Z = np.zeros((max_t+1, max_x+1))
    for i, t_x in enumerate(np.arange(max_t+1)):
{'fraction_non_alphanumeric': 0.10909090909090909, 'fraction_numerical': 0.004110671936758893, 'mean_word_length': 3.614150255288111, 'pattern_counts': {'":': 5, '<': 3, '<?xml version=': 0, '>': 3, '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}}
{'dir': 'git-commits-cleaned', 'id': '7181946', 'n_tokens_mistral': 2042, 'n_tokens_neox': 1948, 'n_words': 510}