Juan Acevedo commited on
Commit
e39b21b
·
1 Parent(s): 7b1e84b
Files changed (1) hide show
  1. app.py +134 -2
app.py CHANGED
@@ -28,6 +28,115 @@ df_viz['Cluster'] = cluster_predictions
28
  X_scaled = pipeline.named_steps['scaler'].transform(df_features)
29
  X_pca = pipeline.named_steps['pca'].transform(X_scaled)
30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  def create_cluster_plot():
32
  """Crear el gráfico de scatter de los clusters"""
33
  plt.figure(figsize=(10, 6))
@@ -66,7 +175,8 @@ def get_cluster_summary(selected_cluster):
66
  for var in important_vars:
67
  if var in cluster_data.columns:
68
  mean_val = cluster_data[var].mean()
69
- summary_data.append([var, round(mean_val, 2)])
 
70
 
71
  return pd.DataFrame(summary_data, columns=['Variable', 'Promedio'])
72
 
@@ -117,7 +227,24 @@ def predict_new_customer(customer_id, year_birth, income, kidhome, teenhome, rec
117
  # Predecir cluster (el pipeline maneja internamente el scaling y PCA)
118
  predicted_cluster = pipeline.predict(new_customer)[0]
119
 
120
- return f"🎯 El cliente ID {customer_id} pertenece al **Cluster {predicted_cluster}**"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
 
122
  def update_cluster_info(selected_cluster):
123
  """Actualizar información cuando se selecciona un cluster"""
@@ -142,6 +269,11 @@ with gr.Blocks(title="Customer Personality Analysis", theme=gr.themes.Soft()) as
142
  El modelo utiliza **K-Means con PCA** para segmentar clientes en 2 grupos basándose en sus patrones de compra y comportamiento.
143
  """)
144
 
 
 
 
 
 
145
  with gr.Row():
146
  with gr.Column():
147
  # Gráfico de clusters
 
28
  X_scaled = pipeline.named_steps['scaler'].transform(df_features)
29
  X_pca = pipeline.named_steps['pca'].transform(X_scaled)
30
 
31
+ # Diccionario para traducir variables
32
+ VARIABLE_NAMES = {
33
+ 'Year_Birth': 'Año de Nacimiento',
34
+ 'Income': 'Ingresos (log)',
35
+ 'Kidhome': 'Niños en Casa',
36
+ 'Teenhome': 'Adolescentes en Casa',
37
+ 'Recency': 'Días desde Última Compra',
38
+ 'MntWines': 'Gastos en Vinos (log)',
39
+ 'MntFruits': 'Gastos en Frutas (log)',
40
+ 'MntMeatProducts': 'Gastos en Carnes (log)',
41
+ 'MntFishProducts': 'Gastos en Pescados (log)',
42
+ 'MntSweetProducts': 'Gastos en Dulces (log)',
43
+ 'MntGoldProds': 'Gastos en Productos Premium (log)',
44
+ 'NumWebPurchases': 'Compras Web',
45
+ 'NumCatalogPurchases': 'Compras por Catálogo',
46
+ 'NumStorePurchases': 'Compras en Tienda',
47
+ 'NumWebVisitsMonth': 'Visitas Web por Mes'
48
+ }
49
+
50
+ def analyze_clusters():
51
+ """Analizar y describir las características de cada cluster"""
52
+ cluster_descriptions = {}
53
+
54
+ for cluster in [0, 1]:
55
+ cluster_data = df_viz[df_viz['Cluster'] == cluster]
56
+
57
+ # Calcular promedios de variables clave
58
+ avg_income = np.exp(cluster_data['Income'].mean()) - 1 # Deshacer log1p
59
+ avg_wines = np.exp(cluster_data['MntWines'].mean()) - 1
60
+ avg_meat = np.exp(cluster_data['MntMeatProducts'].mean()) - 1
61
+ avg_gold = np.exp(cluster_data['MntGoldProds'].mean()) - 1
62
+ avg_web_purchases = cluster_data['NumWebPurchases'].mean()
63
+ avg_store_purchases = cluster_data['NumStorePurchases'].mean()
64
+ avg_kids = cluster_data['Kidhome'].mean()
65
+ avg_teens = cluster_data['Teenhome'].mean()
66
+
67
+ cluster_descriptions[cluster] = {
68
+ 'avg_income': avg_income,
69
+ 'avg_wines': avg_wines,
70
+ 'avg_meat': avg_meat,
71
+ 'avg_gold': avg_gold,
72
+ 'avg_web': avg_web_purchases,
73
+ 'avg_store': avg_store_purchases,
74
+ 'avg_kids': avg_kids,
75
+ 'avg_teens': avg_teens,
76
+ 'count': len(cluster_data)
77
+ }
78
+
79
+ return cluster_descriptions
80
+
81
+ def get_cluster_interpretation():
82
+ """Generar interpretación de los clusters"""
83
+ cluster_info = analyze_clusters()
84
+
85
+ interpretation = """
86
+ ## 🧠 Interpretación de los Clusters
87
+
88
+ Basándose en el análisis de los datos, nuestro modelo ha identificado dos segmentos principales de clientes:
89
+
90
+ """
91
+
92
+ for cluster in [0, 1]:
93
+ info = cluster_info[cluster]
94
+
95
+ # Determinar el perfil del cluster
96
+ if info['avg_income'] > 50000:
97
+ income_level = "ingresos altos"
98
+ elif info['avg_income'] > 30000:
99
+ income_level = "ingresos medios"
100
+ else:
101
+ income_level = "ingresos bajos"
102
+
103
+ if info['avg_wines'] > 200:
104
+ wine_spending = "alto gasto en vinos"
105
+ elif info['avg_wines'] > 50:
106
+ wine_spending = "gasto moderado en vinos"
107
+ else:
108
+ wine_spending = "bajo gasto en vinos"
109
+
110
+ if info['avg_web'] > info['avg_store']:
111
+ channel_pref = "prefieren compras online"
112
+ else:
113
+ channel_pref = "prefieren compras en tienda física"
114
+
115
+ family_status = ""
116
+ if info['avg_kids'] + info['avg_teens'] > 1:
117
+ family_status = "con familias más grandes"
118
+ elif info['avg_kids'] + info['avg_teens'] > 0.5:
119
+ family_status = "con hijos"
120
+ else:
121
+ family_status = "sin hijos o familias pequeñas"
122
+
123
+ interpretation += f"""
124
+ ### 🎯 **Cluster {cluster}** ({info['count']} clientes)
125
+
126
+ **Perfil:** Clientes con {income_level}, {wine_spending}, {family_status} y que {channel_pref}.
127
+
128
+ **Características principales:**
129
+ - 💰 Ingresos promedio: ${info['avg_income']:,.0f}
130
+ - 🍷 Gasto en vinos: ${info['avg_wines']:.0f}
131
+ - 🥩 Gasto en carnes: ${info['avg_meat']:.0f}
132
+ - ✨ Productos premium: ${info['avg_gold']:.0f}
133
+ - 🛒 Compras web: {info['avg_web']:.1f} | Tienda: {info['avg_store']:.1f}
134
+ - 👶 Niños: {info['avg_kids']:.1f} | Adolescentes: {info['avg_teens']:.1f}
135
+
136
+ """
137
+
138
+ return interpretation
139
+
140
  def create_cluster_plot():
141
  """Crear el gráfico de scatter de los clusters"""
142
  plt.figure(figsize=(10, 6))
 
175
  for var in important_vars:
176
  if var in cluster_data.columns:
177
  mean_val = cluster_data[var].mean()
178
+ var_name = VARIABLE_NAMES.get(var, var)
179
+ summary_data.append([var_name, round(mean_val, 2)])
180
 
181
  return pd.DataFrame(summary_data, columns=['Variable', 'Promedio'])
182
 
 
227
  # Predecir cluster (el pipeline maneja internamente el scaling y PCA)
228
  predicted_cluster = pipeline.predict(new_customer)[0]
229
 
230
+ # Obtener descripción del cluster
231
+ cluster_info = analyze_clusters()
232
+ info = cluster_info[predicted_cluster]
233
+
234
+ result = f"""
235
+ ## 🎯 Resultado de la Predicción
236
+
237
+ **El cliente ID {customer_id} pertenece al Cluster {predicted_cluster}**
238
+
239
+ ### 📊 Características del Cluster {predicted_cluster}:
240
+ - 👥 Total de clientes similares: {info['count']}
241
+ - 💰 Ingresos promedio del grupo: ${info['avg_income']:,.0f}
242
+ - 🍷 Gasto promedio en vinos: ${info['avg_wines']:.0f}
243
+ - 🥩 Gasto promedio en carnes: ${info['avg_meat']:.0f}
244
+ - 🛒 Compras web vs tienda: {info['avg_web']:.1f} vs {info['avg_store']:.1f}
245
+ """
246
+
247
+ return result
248
 
249
  def update_cluster_info(selected_cluster):
250
  """Actualizar información cuando se selecciona un cluster"""
 
269
  El modelo utiliza **K-Means con PCA** para segmentar clientes en 2 grupos basándose en sus patrones de compra y comportamiento.
270
  """)
271
 
272
+ # Agregar interpretación de clusters
273
+ gr.Markdown(get_cluster_interpretation())
274
+
275
+ gr.Markdown("---")
276
+
277
  with gr.Row():
278
  with gr.Column():
279
  # Gráfico de clusters