def feat_engineer(df):
    """Feature engineering - creating new features

    Parameters
    ----------
    df : pd.DataFrame
        Input dataframe

    Returns
    -------
    pd.DataFrame
        Dataframe with new features
    """
    df["total_page_view"] = (
        df["Administrative"] + df["Informational"] + df["ProductRelated"]
    )

    df["total_duration"] = (
        df["Administrative_Duration"]
        + df["Informational_Duration"]
        + df["ProductRelated_Duration"]
    )

    df["product_view_percent"] = df["ProductRelated"] / df["total_page_view"]
    df["product_dur_percent"] = df["ProductRelated_Duration"] / df["total_duration"]
    df["ave_product_duration"] = df["ProductRelated_Duration"] / df["ProductRelated"]
    df["page_values_x_bounce_rate"] = df["PageValues"] * (1 - df["BounceRates"])
    df["page_values_per_product_view"] = df["PageValues"] / df["ProductRelated"]
    df["page_values_per_product_dur"] = df["PageValues"] / df["ProductRelated_Duration"]

    # some nans are generated in the new features due to zero division caused by
    # totals that are equal to zero (e.g. total_page_view = 0)
    nan_replacements = {
        "product_view_percent": 0,
        "product_dur_percent": 0,
        "ave_product_duration": 0,
        "page_values_x_bounce_rate": 0,
        "page_values_per_product_view": 0,
        "page_values_per_product_dur": 0,
    }

    # correct values should be zero, updated here
    df = df.fillna(nan_replacements)

    return df