Amit-kr26's picture
HF Spaces deployment
c9f187d
Raw
History Blame Contribute Delete
1.9 kB
"""Customer Lifetime Value feature computation."""
import pandas as pd
from sqlalchemy import Engine, text
def compute_clv_features(engine: Engine) -> pd.DataFrame:
"""
Compute CLV-related features per customer_unique_id.
Returns a DataFrame with columns:
customer_unique_id, customer_key, avg_order_value, order_count,
tenure_days, avg_days_between_orders, predicted_clv
"""
sql = text("""
SELECT
dc.customer_unique_id,
COUNT(DISTINCT f.order_id) AS order_count,
SUM(f.price + f.freight_value) AS total_revenue,
AVG(f.price + f.freight_value) AS avg_order_value,
MAX(f.order_date_id) - MIN(f.order_date_id) AS tenure_days,
AVG(f.review_score) AS avg_review_score,
AVG(f.days_to_delivery) AS avg_days_to_delivery,
AVG(CASE WHEN f.is_late THEN 1.0 ELSE 0.0 END) AS late_delivery_rate
FROM warehouse.fact_orders f
JOIN warehouse.dim_customers dc ON f.customer_key = dc.customer_key
WHERE f.order_status NOT IN ('canceled', 'unavailable')
GROUP BY dc.customer_unique_id
""")
with engine.connect() as conn:
df = pd.read_sql(sql, conn)
# Simple CLV estimate: avg_order_value * order_count * quality_factor
# quality_factor reduces CLV for customers with many late deliveries
df["tenure_days"] = df["tenure_days"].fillna(0).astype(int)
df["quality_factor"] = (1.0 - df["late_delivery_rate"].fillna(0) * 0.3).clip(0.5, 1.0)
df["avg_days_between_orders"] = (
df["tenure_days"] / df["order_count"].clip(lower=1)
)
df["predicted_clv"] = (
df["avg_order_value"] * df["order_count"] * df["quality_factor"]
).round(2)
return df