🛍️ Customer Segmentation with RFM

Enter the Recency, Frequency, and Monetary data to find out which segment the customer belongs to.

The customer segment will appear here.
packages = [ "pandas", "scikit-learn", "numpy", "joblib" ] import pandas as pd import joblib from pyodide.http import pyfetch from js import document, console import io # Global variables to store the scaler and model scaler = None model = None async def load_model_and_scaler(): """Asynchronously loads the scaler and .joblib model file.""" global scaler, model if scaler is None or model is None: console.log("Loading the scaler and model...") try: response = await pyfetch('./rfm_cluster_model.joblib') if response.ok: model_bytes = await response.bytes() # joblib.load returns the tuple we saved: (scaler, kmeans_model) scaler, model = joblib.load(io.BytesIO(model_bytes)) console.log("Scaler and model loaded successfully!") else: console.error(f"Error fetching the file: {response.status}") except Exception as e: console.error(f"An error occurred while loading the file: {e}") async def segment_customer(*args, **kwargs): """Function called by the button to segment the customer (final corrected version).""" await load_model_and_scaler() output_div = document.getElementById('output-div') if scaler is None or model is None: output_div.innerText = "Error: Model could not be loaded." return try: recency_val = document.getElementById('recency').value frequency_val = document.getElementById('frequency').value monetary_val = document.getElementById('monetary').value if not recency_val or not frequency_val or not monetary_val: raise ValueError("Fields cannot be empty.") recency = int(recency_val) frequency = int(frequency_val) monetary = float(monetary_val) # Creates the input DataFrame with the correct column names input_df = pd.DataFrame([[recency, frequency, monetary]], columns=['Recency', 'Frequency', 'Monetary']) # STEP 1: Apply scaling scaled_input_array = scaler.transform(input_df) # This returns a NumPy Array # --- CORRECTED/ADDED LINE --- # Convert the array back to a DataFrame with column names scaled_input_df = pd.DataFrame(scaled_input_array, columns=input_df.columns) # STEP 2: Use the model to predict the cluster from the scaled DataFrame # --- CHANGED LINE --- cluster = model.predict(scaled_input_df)[0] # Map the cluster number to a user-friendly description cluster_map = { 0: "At-Risk Customers (Purchased a long time ago)", 1: "Best Customers (Champions)", 2: "Loyal Customers (Potential for growth)", 3: "New Customers (Low value, but recent)" } segment_name = cluster_map.get(cluster, "Unknown Segment") # Display the result on the screen output_div.innerText = f"Segment: {segment_name}" except ValueError as e: output_div.innerText = "Error: Please fill all fields with valid numbers." except Exception as e: console.error(f"An unexpected error occurred: {e}") output_div.innerText = "An unexpected error occurred. Check the console (F12)."