Data Science per E-commerce: Identificare i Serial Returners con PCA e Python

Cerca:

Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors
Come ridurre i resi e-commerce con i dati

C’è una bugia che ci raccontiamo spesso davanti ai report di fine mese:

se il grafico del fatturato sale, va tutto bene.

Non è vero.

Ho visto aziende investire budget enormi per acquisire clienti che, a conti fatti, costavano più di quanto rendessero. Il problema non è la mancanza di dati, anzi. Ne abbiamo troppi e spesso guardiamo quelli sbagliati.

Ci ossessioniamo sul volume (quanto comprano?) ignorando quasi sempre l’efficienza (quanto ci costa servirli?).

Un cliente che spende 1.000€ ma ne restituisce 400€ e acquista solo col 30% di sconto non è una risorsa: è un danno logistico.

Ho visto e-commerce festeggiare record di vendite al Black Friday, per poi andare in crisi di liquidità a gennaio quando il 40% della merce è tornata indietro danneggiata.

Ma in un foglio Excel classico, quel cliente appare identico a uno che ne spende 600€ a prezzo pieno e non fa mai un reso. Oggi vediamo come smettere di farsi ingannare dai numeri aggregati, usando la Data Science non per fare accademia, ma per pulire la lente con cui guardiamo il business.

In questo scenario, il Data Scientist non è un semplice “masticatore di numeri”, ma un traduttore: deve prendere un groviglio di 5 o 10 variabili e sintetizzarle in direzioni strategiche chiare. La PCA (Principal Component Analysis) non serve a fare calcoli eleganti, serve a pulire la lente con cui osserviamo il business, separando chi porta valore reale da chi erode i margini.

Pubblicità


Il Caso Studio: Trasformare 5 Variabili in Strategia

Immaginiamo un dataset di 1.000 clienti di un e-commerce di moda, definiti da:

  • X1 (Ordini): Frequenza d’acquisto.

  • X2 (Spesa): Valore monetario.

  • X3 (Varietà): Ampiezza del catalogo esplorato.

  • X4 (Sconti): Dipendenza dalle promozioni.

  • X5 (Resi): Impatto logistico.

1. La Selezione: Quanta informazione è “abbastanza”?

La PCA trasforma queste variabili in Componenti Principali (PC). Ecco i risultati:

Componente Autovalore (λ) Varianza Spiegata Varianza Cumulativa
PC1 2,40 48% 48%
PC2 1,30 26% 74%
PC3 0,80 16% 90%
PC4 0,35 7% 97%
PC5 0,15 3% 100%

L’occhio critico del Data Scientist:

Se seguissimo il Criterio di Kaiser (lambda > 1), ci fermeremmo a 2 componenti. Ma attenzione: con 2 componenti copriamo il 74% della varianza. Se il business richiede una precisione chirurgica sui resi (che spesso finiscono nelle componenti “minori”), dovremmo includere la terza (PC3) per arrivare al 90%.

Tuttavia, per la visualizzazione e la semplicità di marketing, la struttura a 2 dimensioni (PC1 e PC2) è il compromesso ideale.

2. Interpretazione: Dare un nome ai nuovi assi

Non chiamiamole PC1 e PC2. In un report direzionale, queste diventano:

  • PC1 – “Indice di Vitalità” (Loadings positivi su Ordini, Spesa, Varietà): Rappresenta quanto il cliente è “dentro” l’ecosistema del brand.

  • PC2 – “Indice di Rischio Operativo” (Loadings alti su Sconti e Resi): Identifica chi compra solo se stimolato dal prezzo e chi restituisce troppo, gravando sui costi di spedizione.

Forse potrebbe interessarti anche:  Introduzione alle Tecniche di Clustering : K-Means Clustering

3. I Segmenti: Chi stiamo premiando?

Dalla proiezione dei dati sui nuovi assi, emergono tre figure chiare:

  • Cluster A: I Top Clients (PC1+, PC2-). Sono la spina dorsale dell’azienda. Comprano a prezzo pieno e tengono i prodotti.

    • Strategia: Non disturbateli con sconti. Offrite loro privilegi immateriali (anteprime, community, eventi).

  • Cluster B: I Serial Returners (PC1-, PC2+). Spesso scambiati per “buoni clienti” perché fanno volumi, ma il loro margine netto è vicino allo zero o negativo.

    • Strategia: Introdurre policy di reso più restrittive o eliminare la spedizione gratuita per questo specifico segmento.

  • Cluster C: I Potenziali (PC1 media, PC2 media). La classe media dell’e-commerce.

    • Strategia: Cross-selling. L’obiettivo è aumentare la loro varietà di acquisto (PC1) senza farli scivolare nel vizio del reso (PC2).

Pubblicità

Implementazione Python: PCA + K-means Clustering

Per passare dalla teoria alla pratica, ecco uno script Python completo che simula 1.000 clienti, riduce le dimensioni e identifica automaticamente i segmenti di mercato.

# ============================================
# PCA + K-means: Segmentazione Avanzata (Coerente con la Strategia)
# ============================================

import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import seaborn as sns

# --------------------------------------------
# 1. Creazione Dataset con Archetipi Definiti
# --------------------------------------------
np.random.seed(42)

# Definiamo 3 archetipi comportamentali per garantire che i pattern esistano
# A: VIP (Tanti ordini, Spesa alta, Resi bassi, Sconti bassi)
# B: Serial Returners (Tanti ordini, Spesa media, Resi altissimi, Cacciatori di sconti)
# C: Standard (Pochi ordini, Spesa bassa, Resi medi)

n_vip = 200
n_ret = 200
n_std = 600

# Generazione VIP
vip_data = pd.DataFrame({
    "Ordini": np.random.poisson(12, n_vip),
    "Spesa": np.random.normal(120, 15, n_vip),
    "Varieta": np.random.normal(8, 1, n_vip),
    "Sconti": np.random.normal(5, 2, n_vip),   # Poco sconto
    "Resi": np.random.normal(5, 2, n_vip)      # Reso fisiologico
})

# Generazione Serial Returners
ret_data = pd.DataFrame({
    "Ordini": np.random.poisson(10, n_ret),    # Comprano molto anche loro
    "Spesa": np.random.normal(90, 10, n_ret),
    "Varieta": np.random.normal(5, 2, n_ret),
    "Sconti": np.random.normal(30, 5, n_ret),  # Molto sconto
    "Resi": np.random.normal(45, 5, n_ret)     # Reso patologico
})

# Generazione Utenti Standard
std_data = pd.DataFrame({
    "Ordini": np.random.poisson(3, n_std),
    "Spesa": np.random.normal(40, 10, n_std),
    "Varieta": np.random.normal(2, 1, n_std),
    "Sconti": np.random.normal(15, 5, n_std),
    "Resi": np.random.normal(10, 5, n_std)
})

df = pd.concat([vip_data, ret_data, std_data]).reset_index(drop=True)

# Correzione valori negativi non realistici
df[df < 0] = 0 

print("Statistiche descrittive del dataset simulato:")
print(df.describe().round(1))

# --------------------------------------------
# 2. Standardizzazione e PCA
# --------------------------------------------
scaler = StandardScaler()
X_scaled = scaler.fit_transform(df)

pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)

# --- CORREZIONE DEL SEGNO (Step Cruciale per la coerenza) ---
# Vogliamo assicurarci che:
# PC1 cresca con la Spesa/Ordini (Vitalità)
# PC2 cresca con i Resi/Sconti (Rischio)

# Controlliamo il peso (loading) della variabile 'Spesa' sulla PC1
idx_spesa = 1 
if pca.components_[0, idx_spesa] < 0:
    X_pca[:, 0] = -X_pca[:, 0]  # Invertiamo asse PC1
    pca.components_[0] = -pca.components_[0]

# Controlliamo il peso della variabile 'Resi' sulla PC2
idx_resi = 4 
if pca.components_[1, idx_resi] < 0:
    X_pca[:, 1] = -X_pca[:, 1]  # Invertiamo asse PC2
    pca.components_[1] = -pca.components_[1]

# Salviamo i risultati nel DataFrame
df["Indice_Vitalita"] = X_pca[:, 0] # Ex PC1
df["Indice_Rischio"]  = X_pca[:, 1] # Ex PC2

print(f"\nVarianza spiegata cumulativa: {np.sum(pca.explained_variance_ratio_)*100:.1f}%")

# --------------------------------------------
# 3. K-means Clustering e Auto-Labeling
# --------------------------------------------
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)
df["Cluster_ID"] = kmeans.fit_predict(X_pca)

# Calcolo dei centroidi per capire chi è chi
centroidi = df.groupby("Cluster_ID")[["Indice_Vitalita", "Indice_Rischio"]].mean()

# --- MAPPATURA INTELLIGENTE (Dal numero al nome business) ---
# Logica:
# 1. Il cluster con Rischio (PC2) più alto è "Serial Returner"
# 2. Tra i rimanenti, quello con Vitalità (PC1) più alta è "Top Client"
# 3. L'ultimo è "Standard/Potential"

cluster_map = {}

# Trova i Serial Returners (Max PC2)
id_serial = centroidi["Indice_Rischio"].idxmax()
cluster_map[id_serial] = "Serial Returners (Rischio Alto)"

# Escludiamo i serial returners per trovare i VIP
rimanenti = centroidi.drop(id_serial)
id_vip = rimanenti["Indice_Vitalita"].idxmax()
cluster_map[id_vip] = "Top Clients (Valore Alto)"

# L'ultimo rimasto
id_std = list(set(centroidi.index) - {id_serial, id_vip})[0]
cluster_map[id_std] = "Potentials (Segmento Medio)"

# Applichiamo le etichette
df["Segmento"] = df["Cluster_ID"].map(cluster_map)

# --------------------------------------------
# 4. Visualizzazione Strategica
# --------------------------------------------
plt.figure(figsize=(12, 8))
sns.scatterplot(
    data=df,
    x="Indice_Vitalita", 
    y="Indice_Rischio",
    hue="Segmento",
    palette={"Top Clients (Valore Alto)": "#2ecc71",       # Verde
             "Serial Returners (Rischio Alto)": "#e74c3c", # Rosso
             "Potentials (Segmento Medio)": "#3498db"},    # Blu
    style="Segmento",
    s=80,
    alpha=0.7
)

# Aggiungiamo linee per dividere i quadranti (origine degli assi)
plt.axhline(0, color='grey', linestyle='--', linewidth=0.8)
plt.axvline(0, color='grey', linestyle='--', linewidth=0.8)

plt.title("Mappa Strategica Clienti: Valore vs Rischio Operativo", fontsize=15)
plt.xlabel("Indice di Vitalità (Volumi e Varietà) →", fontsize=12)
plt.ylabel("Indice di Rischio (Resi e Sconti) →", fontsize=12)
plt.legend(title="Strategia Assegnata", loc='upper right')
plt.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

# --------------------------------------------
# 5. Output per il Marketing (Actionable Insights)
# --------------------------------------------
print("\n--- ANALISI DEI SEGMENTI PER IL CRM ---")
summary = df.groupby("Segmento")[["Ordini", "Spesa", "Resi", "Sconti"]].mean().round(1)
print(summary)

 

Forse potrebbe interessarti anche:  Marketing Mix Modeling con Python: Ridge, inferenza bayesiana e ottimizzazione del budget

 

Statistiche descrittive del dataset simulato:
       Ordini   Spesa  Varieta  Sconti    Resi
count  1000.0  1000.0   1000.0  1000.0  1000.0
mean      6.1    66.0      3.8    16.1    15.8
std       4.6    34.8      2.7     9.2    15.4
min       0.0     7.2      0.0     0.0     0.0
25%       2.0    37.8      1.7     8.5     5.5
50%       4.0    49.9      2.7    15.0     9.6
75%      10.0    95.0      6.3    22.0    16.6
max      21.0   166.2     11.3    43.8    60.5

Varianza spiegata cumulativa: 88.4%
--- ANALISI DEI SEGMENTI PER IL CRM ---
                                 Ordini  Spesa  Resi  Sconti
Segmento                                                    
Potentials (Segmento Medio)         2.9   40.1   9.6    15.0
Serial Returners (Rischio Alto)     9.8   90.5  45.0    30.0
Top Clients (Valore Alto)          11.8  119.3   5.2     5.4

 

PC2: La Dimensione “Invisibile” del Rischio Operativo

Notate il Cluster “Serial Returners”:

  • Fanno volumi importanti (9.8 ordini, quasi come i Top Clients).

  • Spendono bene (90€ di media).

  • Se guardassimo solo il fatturato, li tratteremmo come VIP.

  • La realtà: Hanno un tasso di reso medio di 45€ (il 50% della merce torna indietro!) e comprano solo con sconti del 30%.

Questo è il pattern comportamentale noto come Low-Commitment Buying. L’acquisto compulsivo di chi non paga il prezzo pieno crea una barriera psicologica più bassa verso il reso. Se il prodotto non è perfetto, la “perdita percepita” è minima e il reso diventa la via d’uscita predefinita.

Ignorare la PC2 significa premiare clienti che distruggono il margine netto con costi logistici (10-20€ a reso) e deprezzamento dello stock.


Dalla PCA all’Inbox: Strategia CRM

Una volta identificati i cluster, il lavoro del Data Scientist finisce e inizia quello del Marketing Automation Specialist.

1. Top Clients (PC1 Alta, PC2 Bassa)

  • Obiettivo: Massimizzare il Lifetime Value (LTV).

  • Azione: Email di “Conciergerie”. Accesso anticipato alle nuove collezioni. Zero sconti, solo privilegi immateriali.

Forse potrebbe interessarti anche:  Catene di Markov in Python: Modellare Funnel, Retention e Churn oltre le classiche dashboard

2. Serial Returners (PC2 Alta)

  • Obiettivo: De-marketing e riduzione perdite.

  • Azione: Esclusione dai saldi privati. Invio di guide ultra-dettagliate alle taglie per prevenire l’errore. Policy di reso più restrittive (es. niente reso gratuito sotto una certa soglia).

3. Potentials (Media)

  • Obiettivo: Cross-selling.

  • Azione: Bundle offers (“Compra il look completo”) per aumentare la varietà (PC1) senza viziarli con sconti eccessivi (PC2).

Commento Tecnico e Applicativo

Perché questo esercizio è interessante?

Questo scenario è paradigmatico perché affronta il problema della multicollinearità. In un e-commerce, “Ordini annui” e “Spesa media” sono quasi sempre correlati. Usarli entrambi in un modello di clustering grezzo darebbe un peso eccessivo alla dimensione “Volume”, oscurando variabili critiche come i “Resi”.

La PCA “pulisce” queste sovrapposizioni, creando assi ortogonali (indipendenti). Il valore reale sta nella capacità di isolare il comportamento d’acquisto dal costo logistico.

 

Sintesi: Perchè usiamo PC1 e PC2 per il Clustering?

Eseguire il K-means direttamente sulle 5 variabili originali soffrirebbe della multicollinearità. In un e-commerce, “Ordini annui” e “Spesa media” dicono quasi la stessa cosa (Volume). Usarli entrambi darebbe un peso doppio alla dimensione “Volume”, schiacciando variabili critiche ma con valori numerici diversi come i “Resi”.

La PCA “pulisce” queste sovrapposizioni. Il valore reale sta nella capacità di isolare matematicamente il comportamento d’acquisto dal costo logistico, permettendoci di vedere i clienti per quello che sono veramente: profitto o perdita.

Pubblicità