La estadística es una herramienta poderosa que nos permite abordar problemas complejos y responder preguntas que surgen al observar datos o patrones por primera vez. Un ejemplo de esto podría ser analizar la personalidad de los clientes en un supermercado. Preguntas como ¿Realmente este grupo es diferente al otro? ¿En qué medida? ¿Debería centrarme más en este grupo para mejorar su experiencia y mis ventas? son clave para tomar decisiones acertadas.
Si bien las visualizaciones pueden ayudarnos a comprender los datos de manera rápida, no siempre son 100% confiables. Podríamos observar diferencias claras entre grupos, pero esas diferencias pueden no ser estadísticamente significativas.
Aquí es donde entra en juego la estadística: no solo nos ayuda a analizar los datos de manera más profunda, sino que nos da la seguridad necesaria para validar nuestras suposiciones. Como científicos de datos o profesionales que ayudan a tomar decisiones, debemos ser conscientes de que un análisis incorrecto puede llevar a decisiones equivocadas, lo que resultaría en pérdida de tiempo y dinero. Por eso, es crucial que nuestras conclusiones estén bien fundamentadas, respaldadas por evidencia estadística.
La verdadera satisfacción llega cuando vemos los resultados de nuestro análisis reflejados en cambios efectivos dentro de la empresa, mejoras en la experiencia del cliente, y, en última instancia, un impacto positivo en las ventas y operaciones. ¡Es una sensación increíble haber sido parte de ese proceso!
Para ayudarte a desarrollar esta habilidad desarrollaremos en este artículo en Análisis de la personalidad de clientes de un supermercado, utilizaremos el Dataset de Kaggle Customer Personality Analysis: https://www.kaggle.com/datasets/imakash3011/customer-personality-analysis
En este análisis, exploraremos el comportamiento de los clientes de un supermercado con el objetivo de extraer información valiosa de los datos. Buscaremos responder las siguientes preguntas:
- ¿Existe alguna diferencia significativa en el gasto total por Educación?
- ¿Existe alguna diferencia significativa en el gasto total por Cantidad de hijos?
- ¿Existe alguna diferencia significativa en el gasto total por Estado Marital?
Si bien este análisis podría extenderse mucho más, nos centraremos en responder estas tres preguntas, ya que ofrecen un gran poder explicativo. A lo largo del artículo, te mostraremos cómo podemos abordar estas cuestiones y cómo, mediante el mismo enfoque, podríamos responder muchas más preguntas.
En este artículo exploraremos análisis estadísticos como el test Kolmogorov-Smirnov, la prueba de Levene, y cómo saber cuándo aplicar ANOVA o Kruskal-Wallis. Puede que estos nombres te suenen desconocidos, pero no te preocupes, los explicaré de manera sencilla para que los entiendas sin complicaciones.
A continuación, te mostraré el código en Python y los pasos a seguir para realizar estos análisis estadísticos de forma efectiva.
1. Primeros pasos
Importamos las librerías de Python necesarias.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import os
from scipy import stats
from scipy.stats import kstest
from scipy.stats import levene
import scikit_posthocs as sp
Ahora podemos optar por dos formas para cargar el archivo.csv, obtenemos directamente el archivo o podemos obtener el enlace de kaggle, justo en el botón de descargar.
#pip install kagglehub
import kagglehub
# Download latest version
path = kagglehub.dataset_download("imakash3011/customer-personality-analysis")
print("Path to dataset files:", path)
#Obtenemos el nombre del archivo
nombre_archivo = os.listdir(path)[0]
nombre_archivo
'marketing_campaign.csv'
#Cargamos el archivo en un DataFrame
df = pd.read_csv(path + '\\' + nombre_archivo,sep='\t')
df.head(2)
ID | Year_Birth | Education | Marital_Status | Income | Kidhome | Teenhome | Dt_Customer | Recency | MntWines | MntFruits | MntMeatProducts | MntFishProducts | MntSweetProducts | MntGoldProds | NumDealsPurchases | NumWebPurchases | NumCatalogPurchases | NumStorePurchases | NumWebVisitsMonth | AcceptedCmp3 | AcceptedCmp4 | AcceptedCmp5 | AcceptedCmp1 | AcceptedCmp2 | Complain | Z_CostContact | Z_Revenue | Response | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 5524 | 1957 | Graduation | Single | 58138.0 | 0 | 0 | 04-09-2012 | 58 | 635 | 88 | 546 | 172 | 88 | 88 | 3 | 8 | 10 | 4 | 7 | 0 | 0 | 0 | 0 | 0 | 0 | 3 | 11 | 1 |
1 | 2174 | 1954 | Graduation | Single | 46344.0 | 1 | 1 | 08-03-2014 | 38 | 11 | 1 | 6 | 2 | 1 | 6 | 2 | 1 | 1 | 2 | 5 | 0 | 0 | 0 | 0 | 0 | 0 | 3 | 11 | 0 |
2 | 4141 | 1965 | Graduation | Together | 71613.0 | 0 | 0 | 21-08-2013 | 26 | 426 | 49 | 127 | 111 | 21 | 42 | 1 | 8 | 2 | 10 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 3 | 11 | 0 |
Para tener una mejor noción del conjunto de datos que analizaremos te indicare el significado de cada columna.
Columnas:
-
Personas:
- ID: identificador único del cliente
- Year_Birth: año de nacimiento del cliente.
- Education: nivel de educación del cliente.
- Marital_Status: estado civil del cliente
- Income: ingresos anuales del hogar del cliente
- Kidhome: Número de niños en el hogar del cliente
- Teenhome: Número de adolescentes en el hogar del cliente
- Dt_Customer: Fecha de alta del cliente en la empresa
- Recency: número de días desde la última compra del cliente.
- Complain: 1 si el cliente se quejó en los últimos 2 años, 0 en caso contrario
-
Productos:
- MntWines: Cantidad gastada en vino en los últimos 2 años.
- MntFruits: Monto gastado en frutas en los últimos 2 años.
- MntMeatProducts: Cantidad gastada en carne en los últimos 2 años.
- MntFishProducts: cantidad gastada en pescado en los últimos 2 años.
- MntSweetProducts: cantidad gastada en dulces en los últimos 2 años.
- MntGoldProds: cantidad gastada en oro en los últimos 2 años.
-
Promoción:
- NumDealsPurchases: Número de compras realizadas con descuento.
- AcceptedCmp1: 1 si el cliente aceptó la oferta en la primera campaña, 0 en caso contrario.
- AcceptedCmp2: 1 si el cliente aceptó la oferta en la segunda campaña, 0 en caso contrario.
- AcceptedCmp3: 1 si el cliente aceptó la oferta en la tercera campaña, 0 en caso contrario.
- AcceptedCmp4: 1 si el cliente aceptó la oferta en la cuarta campaña, 0 en caso contrario.
- AcceptedCmp5: 1 si el cliente aceptó la oferta en la quinta campaña, 0 en caso contrario.
- Response: 1 si el cliente aceptó la oferta en la última campaña, 0 en caso contrario
-
Lugar:
- NumWebPurchases: Número de compras realizadas a través del sitio web de la empresa.
- NumCatalogPurchases: Número de compras realizadas mediante un catálogo.
- NumStorePurchases: Número de compras realizadas directamente en tiendas.
- NumWebVisitsMonth: Número de visitas al sitio web de la empresa en el último mes.
Sí, son muchas columnas, sin embargo aquí solo utilizaremos unas cuantas, para no extendernos mucho, de todas formas puedes aplicar los mismo pasos para las demás columnas.
Ahora, verificaremos que no tengamos datos nulos
df.isna().sum()
ID 0
Year_Birth 0
Education 0
Marital_Status 0
Income 24
Kidhome 0
Teenhome 0
Dt_Customer 0
Recency 0
MntWines 0
MntFruits 0
MntMeatProducts 0
MntFishProducts 0
MntSweetProducts 0
MntGoldProds 0
NumDealsPurchases 0
NumWebPurchases 0
NumCatalogPurchases 0
NumStorePurchases 0
NumWebVisitsMonth 0
AcceptedCmp3 0
AcceptedCmp4 0
AcceptedCmp5 0
AcceptedCmp1 0
AcceptedCmp2 0
Complain 0
Z_CostContact 0
Z_Revenue 0
Response 0
dtype: int64
Podemos notar que tenemos 24 datos nulos en la columna Income, sin embargo esta columna no será utilizada en este análisis por ende no haremos nada con ella, en caso que tu la quieras usar, deberás de verificar realizar una de estas dos opciones:
- Imputar los datos faltantes si no representa más de 5% del total de datos(recomendación).
- Eliminar los datos nulos.
2. Configurar el Dataset para el análisis
Nos quedaremos con las columnas que sean de nuestro interés, como educación, hijos, estado marital, cantidad de gasto por categoria de producto, entre otros.
#Nos quedamos con las columnas de interes
df_2 = df[['Education','Kidhome','Teenhome','Marital_Status','NumDealsPurchases','MntWines',
'MntFruits','MntMeatProducts','MntFishProducts','MntSweetProducts','MntGoldProds']].copy()
Calculamos el gasto total sumando los gastos de todas las categorías de producto.
df_2['Total_Spend'] = df_2['MntWines'] + df_2['MntFruits'] + df_2['MntMeatProducts'] + df_2['MntFishProducts'] + df_2['MntSweetProducts'] + df_2['MntGoldProds']
Calculamos la cantidad de hijos de cada cliente, sumando la cantidad de hijos pequeños y adolescentes.
df_2['Children_Count'] = df_2['Kidhome'] + df_2['Teenhome']
Una vez hecho los cálculos, volvemos a reducir el tamaño de las columnas para quedarnos con aquellas de interés.
df_2 = df_2[['Education','Marital_Status','NumDealsPurchases','Total_Spend','Children_Count']]
Como recomendación deberíamos categorizar los valores de nuestra columna Education y Marital_Status, ¿Porqué? Estos siguen un orden, tenemos datos como PhD (Doctorado) que es más elevado con un Master (Maestría), esto nos proporcionará orden y mayor legibilidad a nuestro conjunto de datos.
2.1. Columna Education
df_2['Education'].unique()
array(['Graduation', 'PhD', 'Master', 'Basic', '2n Cycle'], dtype=object)
education_order = ['Basic', '2n Cycle', 'Graduation', 'Master', 'PhD']
df_2['Education'] = df_2['Education'].astype('category')
df_2['Education'] = df_2['Education'].cat.reorder_categories(
new_categories=education_order,
ordered=True
)
df_2['Education'].unique()
['Graduation', 'PhD', 'Master', 'Basic', '2n Cycle']
Categories (5, object): ['Basic' < '2n Cycle' < 'Graduation' < 'Master' < 'PhD']
2.2. Columna Marital_Status
Aquí juntaré algunos valores, ya que es conveniente para evitar valores que tengan significados similares, como 'Alone' y 'Single'.
marital_mapping = {
'Single': 'Single',
'Alone': 'Single',
'Together': 'Together',
'Married': 'Married',
'Divorced': 'Divorced',
'Widow': 'Widow',
'YOLO': 'Others',
'Absurd': 'Others'
}
df_2['Marital_Status'] = df_2['Marital_Status'].map(marital_mapping)
marital_order = ['Single','Together','Married', 'Divorced', 'Widow','Others']
df_2['Marital_Status'] = df_2['Marital_Status'].astype('category')
df_2['Marital_Status'] = df_2['Marital_Status'].cat.reorder_categories(
new_categories=marital_order,
ordered=True
)
3. Análisis Exploratorio de Datos (EDA)
3.1. Education
#Gráfico de Barras
plt.figure(figsize=(10,6))
sns.barplot(data=df_2,x='Education',y='Total_Spend',errorbar=None,palette='Blues')
plt.xlabel("Educación",size=14)
plt.ylabel("Gasto Total (Últimos 2 años)",size=14)
plt.title("Gasto Total (Últimos 2 años) por Nivel de Educación",size=16,color='green')
plt.grid(axis='y')
plt.show()
Con el gráfico de barras podemos notar una clara diferencia en el gasto total que tienen los clientes por nivel de educación, siendo Graduation, Master y PhD el grupo gasto similar, sin embargo no sabemos aún si esta diferencia es significativa.
#Diagrama de Cajas
sns.boxplot(data=df_2,x='Education',y='Total_Spend')
plt.xlabel("Educación",size=14)
plt.ylabel("Gasto Total (Últimos 2 años)",size=14)
plt.title("Gasto Total (Últimos 2 años) por Nivel de Educación",size=16,color='green')
plt.show()
Con el diagrama de cajas (Boxplot) podemos apreciar aún más las diferencias entre clases, no solo viendo el gasto total, si no el gasto total medio de todos los niveles de educación, pudiendo notar incluso pequeñas diferencia entre los grupos con más gasto.
Por último veremos el comportamiento de nuestros gastos totales en cada nivel de educación.
# Número de subgráficos necesarios
n = len(education_order)
# Crear los subgráficos
fig, axes = plt.subplots(nrows=1, ncols=n, figsize=(15, 6))
# Si solo hay un subgráfico, axes no es un arreglo, entonces lo convertimos a lista
if n == 1:
axes = [axes]
colors = ['skyblue','orange','green','purple','blue']
# Iterar sobre los niveles educativos y crear el histograma
for i, education_level in enumerate(education_order):
sns.histplot(df_2[df_2['Education'] == education_level]['Total_Spend'], kde=True, ax=axes[i],color=colors[i])
axes[i].set_title(f'{education_level}')
axes[i].set_xlabel('Gasto Total')
axes[i].set_ylabel('Frecuencia')
# Ajustar el layout
plt.tight_layout()
plt.show()
El histograma nos es de mucha ayuda, con el podemos darnos cuenta de que tenemos sesgo en nuestro datos, teniendo una mayor cantidad de datos en compras bajas, lo cual puede ser lógico dependiendo de la frecuencia de compra de cada cliente.
3.2. Marital Status
Con la columna de Marital_Status podemos observar un diferencia más leve entre clases, sin embargo el comportamiento de los datos sigue siendo el mismo, teniendo datos sesgados.
4. Estadística
¿Es realmente significativa esta diferencia?
Si bien observamos una diferencia en el gasto total por grupos de nivel de educación o por estado marital, ¿Es realmente significativa? Este es un punto crucial a considerar. Aunque podamos observar una diferencia visible, esto no garantiza que sea estadísticamente significativa. En el análisis de datos, es fundamental no solo identificar diferencias, sino asegurarse de que esas diferencias sean relevantes y no producto de la casualidad.
Debemos tener especial cuidado con este aspecto, ya que las decisiones que tome la empresa basadas en nuestro análisis pueden involucrar cambios que afecten recursos importantes como tiempo y dinero. Un análisis estadístico adecuado puede ayudar a asegurar que las decisiones sean tomadas con un respaldo sólido, minimizando riesgos y maximizando el impacto positivo.
4.1. Normalidad
Antes de realizar cualquier prueba de varianza, como ANOVA o Kruskal-Wallis, es fundamental verificar si los datos siguen una distribución normal. Dependiendo de los resultados de esta prueba de normalidad, podremos decidir cuál de las dos pruebas utilizar: si los datos son normales, se podrá optar por ANOVA; en caso contrario, utilizaremos Kruskal-Wallis.
La prueba de normalidad la realizaremos con Kolmogorov-Smirnov, ya que nuestro conjunto de datos tiene más de 50 muestras. Esta prueba es adecuada para tamaños de muestra grandes y nos permitirá determinar si los datos siguen una distribución normal, lo que es crucial para decidir qué prueba estadística aplicar posteriormente.
# Realizamos Kolmogorov-Smirnov para cada grupo de Educación
for edu in education_order:
group_data = df_2[df_2['Education'] == edu]['Total_Spend']
ks_stat, ks_p_value = kstest(group_data, 'norm')
print(f"KS para {edu} (Total_Spend): estadístico = {ks_stat}, p-value = {ks_p_value}")
KS para Basic (Total_Spend): estadístico = 1.0, p-value = 0.0
KS para 2n Cycle (Total_Spend): estadístico = 1.0, p-value = 0.0
KS para Graduation (Total_Spend): estadístico = 0.9999997133484281, p-value = 0.0
KS para Master (Total_Spend): estadístico = 1.0, p-value = 0.0
KS para PhD (Total_Spend): estadístico = 0.9999999999999993, p-value = 0.0
Los resultados de la prueba de Kolmogorov-Smirnov (KS) indican que todas las categorías de Education tienen un p-value de 0.0, lo cual significa que rechazamos la hipótesis nula de normalidad. Es decir, los datos en todas las categorías no siguen una distribución normal.
4.2. Homocedasticidad
Luego de la prueba de normalidad, otro análisis importante es la prueba de Levene, que nos permite comprobar si nuestros datos tienen varianza homogénea o heterogénea. Este paso es crucial porque, dependiendo de los resultados, podremos decidir si aplicar pruebas como ANOVA (que asume homogeneidad de varianzas) o Kruskal-Wallis (que no requiere esta condición).
# Realizamos la prueba de Levene para homocedasticidad
edu_groups = [df_2[df_2['Education'] == edu]['Total_Spend'] for edu in education_order]
levene_stat, levene_p_value = levene(*edu_groups)
print(f"Prueba de Levene: estadístico = {levene_stat}, p-value = {levene_p_value}")
Prueba de Levene: estadístico = 18.40361074007475, p-value = 6.8598908557018694e-15
El p-value de la prueba de Levene es extremadamente bajo (6.86×10 −15 ), lo que nos lleva a rechazar la hipótesis nula de homocedasticidad. Esto indica que las varianzas no son homogéneas entre los grupos de Education.
4.3. ¿Que prueba Elegir?
Para explicarlo de manera sencilla la elección de una prueba u otra, presentaré a continuación unos cuadros de resumen.
4.4. Prueba Kruskal-Wallis
¿Por qué usar Kruskal-Wallis?
No requiere normalidad: A diferencia de ANOVA, Kruskal-Wallis es una prueba no paramétrica, lo que significa que no requiere que los datos sigan una distribución normal.
No requiere homocedasticidad: También es menos sensible a la suposición de homocedasticidad (igualdad de varianzas entre grupos), lo cual lo hace robusto en situaciones donde los grupos tienen varianzas diferentes.
Cómo interpretar la prueba Kruskal-Wallis:
Hipótesis nula (H₀): No hay diferencias significativas en las medianas de los grupos (en este caso, los diferentes niveles de educación).
Hipótesis alternativa (H₁): Hay al menos una diferencia significativa en las medianas de los grupos.
education_order
['Basic', '2n Cycle', 'Graduation', 'Master', 'PhD']
group1 = df_2[df_2['Education'] == education_order[0]]['Total_Spend']
group2 = df_2[df_2['Education'] == education_order[1]]['Total_Spend']
group3 = df_2[df_2['Education'] == education_order[2]]['Total_Spend']
group4 = df_2[df_2['Education'] == education_order[3]]['Total_Spend']
group5 = df_2[df_2['Education'] == education_order[4]]['Total_Spend']
stat, p_value = stats.kruskal(group1, group2, group3, group4, group5)
print(f'Estadístico de Kruskal-Wallis: {stat}')
print(f'Valor p: {p_value}')
if p_value < 0.05:
print("Hay diferencias significativas entre los grupos.")
else:
print("No hay diferencias significativas entre los grupos.")
Estadístico de Kruskal-Wallis: 71.01853119952575
Valor p: 1.3833274361973288e-14
Hay diferencias significativas entre los grupos.
Estadístico de Kruskal-Wallis: El valor 71.01853119952575 es el estadístico de la prueba, que refleja la magnitud de la diferencia entre los grupos. Un valor más alto generalmente indica que las diferencias entre los grupos son mayores.
Valor p: El valor 1.38e-14 es muy pequeño (mucho menor que el umbral de significancia común de 0.05), lo que significa que podemos rechazar la hipótesis nula de que todos los grupos tienen el mismo gasto total. En otras palabras, hay evidencia suficiente para afirmar que el gasto total difiere significativamente entre los niveles de educación.
4.5. Prueba Dunn
Bien, ahora que sabemos que realmente existe una diferencia significativa entre los grupos, ¿Cómo podemos identificar en qué grupos específicos se encuentran esas diferencias?
Para ello, utilizaremos la prueba posthoc Dunn, que es una técnica estadística que nos permite realizar comparaciones múltiples entre los grupos. Esta prueba nos ayuda a identificar qué pares de grupos tienen diferencias significativas, ajustando el valor p para controlar el error tipo I (falsos positivos), lo que la hace una herramienta confiable para análisis post-hoc.
# Crear una lista de grupos para la prueba de Dunn
groups = [group1, group2, group3, group4, group5]
# Aplicar la prueba de Dunn para comparar todos los pares de grupos
dunn_result = sp.posthoc_dunn(groups, p_adjust='bonferroni')
# Mostrar los resultados
dunn_result.round(6) #Se redondeo para evitar valores con muchos decimales
Se usa Bonferroni
en Dunn para reducir la probabilidad de cometer un error tipo I al realizar comparaciones múltiples, lo que asegura que las diferencias significativas encontradas sean realmente confiables y no fruto del azar.
Los valores p son los resultados de las comparaciones entre cada par de grupos. Si el valor p es menor que 0.05, indica que hay una diferencia significativa entre esos dos grupos en cuanto al gasto total. Si es mayor que 0.05, no hay diferencia significativa.
Resumen de las diferencias significativas:
- Entre los grupos 1 y 2: Hay una diferencia significativa.
- Entre los grupos 1 y 3: Hay una diferencia significativa.
- Entre los grupos 1 y 4: Hay una diferencia significativa.
- Entre los grupos 1 y 5: Hay una diferencia significativa.
- Entre los grupos 2 y 5: Hay una diferencia significativa.
No hay diferencias significativas entre:
- Grupos 2 y 3
- Grupos 2 y 4
- Grupos 3 y 4
- Grupos 3 y 5
- Grupos 4 y 5
4.6. Analizar los resultados
¿Que podemos concluir de esto?
El grupo 1 (Basic) tiene diferencias significativas en cuanto al gasto total con casi todos los demás grupos.
Los grupos 3 (Graduation), 4 (Master) y 5 (PhD) no presentan diferencias significativas entre ellos, lo que sugiere que el nivel educativo superior no influye de manera significativa en el gasto total entre estos grupos.
En términos prácticos:
- Grupo 1 (Basic):
Este grupo tiene un gasto total significativamente diferente del resto. Las personas con nivel educativo "Basic" (educación básica) presentan un comportamiento de gasto distinto al de los demás niveles educativos.
Esto podría ser clave para diseñar campañas específicas para este grupo, ya que su comportamiento de gasto es único.
- Grupos 3, 4 y 5 (Graduation, Master, PhD):
Estos niveles educativos más altos muestran patrones de gasto similares entre sí, sin diferencias estadísticamente significativas.
Se podría considerar agruparlos para campañas de marketing dirigidas a clientes con nivel educativo superior, optimizando así esfuerzos y recursos al tratarlos como un segmento homogéneo.
Este análisis no solo valida la importancia de segmentar adecuadamente a los clientes, sino que también destaca cómo usar la estadística para respaldar decisiones que maximizan la efectividad de las estrategias de marketing.
Conclusión para Campañas de Marketing
A partir de los resultados del análisis estadístico, se identifican dos segmentos clave basados en el nivel educativo y su comportamiento de gasto:
Segmento 1: Educación Básica (Grupo 1 - Basic)
Perfil: Este grupo tiene un patrón de gasto significativamente diferente respecto a los demás niveles educativos. Esto puede deberse a factores como ingresos más bajos, necesidades específicas o comportamientos únicos en sus compras.
-
Recomendación:
- Diseñar campañas personalizadas, ajustadas a sus necesidades y posibilidades económicas.
- Enfocar promociones en productos accesibles o de alto interés para este segmento.
- Realizar estudios adicionales para identificar qué impulsa sus diferencias de gasto.
Segmento 2: Educación Superior (Grupos 3 - Graduation, 4 - Master, 5 - PhD)
Perfil: Las personas con educación superior (Graduation, Master, PhD) tienen comportamientos de gasto muy similares, sin diferencias significativas entre estos grupos.
-
Recomendación:
- Unificar esfuerzos con campañas dirigidas al segmento completo de educación superior.
- Aprovechar estrategias que resalten calidad, exclusividad o productos premium, ya que podrían alinearse con sus expectativas.
- Optimizar recursos agrupando a estos niveles educativos en un solo target publicitario.
Por si te preguntas, Ahora que sabemos que tenemos diferencias significativas estadísticamente, y que además sabemos que grupos son, ¿Cómo sabremos cual es la diferencia?
Muy fácil, basta con agrupar por educación y ver una estadística como el gasto medio por nivel de educación.
gasto_promedio = df_2.groupby('Education')['Total_Spend'].mean().reset_index()
gasto_promedio
El gasto promedio es una métrica crucial, ya que elimina el efecto del tamaño del grupo, permitiéndonos analizar el comportamiento de gasto a nivel individual. Esto es especialmente útil para identificar tendencias claras y diseñar estrategias de marketing dirigidas de manera más precisa.
¿Notas ahora el poder de la estadística? Es realmente fascinante lo que podemos lograr con una comprensión básica de sus herramientas. Nos permite tomar decisiones informadas y confiables, respaldadas por datos sólidos, lo que a su vez puede llevar a resultados más efectivos y un mayor impacto en nuestras estrategias.
Con este enfoque basado en análisis estadísticos, podemos mejorar la segmentación, personalizar campañas y maximizar el retorno de inversión de manera medible. La estadística no solo se trata de números; es un motor para tomar decisiones estratégicas con confianza.
5. ¿Con ganas de más? Analicemos dos variables más (Marital_Status y Cantidad de hijos).
5.1. Marital_Status
#Prueba de normalidad para Marital Status
for status in marital_order:
group_data = df_2[df_2['Marital_Status'] == status]['Total_Spend']
ks_stat, ks_p_value = kstest(group_data, 'norm')
print(f"KS para {status} (Total_Spend): estadístico = {ks_stat}, p-value = {ks_p_value}")
KS para Single (Total_Spend): estadístico = 0.9999997133484281, p-value = 0.0
KS para Together (Total_Spend): estadístico = 0.9999999999999993, p-value = 0.0
KS para Married (Total_Spend): estadístico = 0.9999999999999993, p-value = 0.0
KS para Divorced (Total_Spend): estadístico = 0.9999999990134123, p-value = 0.0
KS para Widow (Total_Spend): estadístico = 1.0, p-value = 0.0
KS para Others (Total_Spend): estadístico = 1.0, p-value = 0.0
RESULTADO: NO PRESENTA NORMALIDAD
# Realizamos la prueba de Levene para homocedasticidad
status_group = [df_2[df_2['Marital_Status'] == status]['Total_Spend'] for status in marital_order]
levene_stat, levene_p_value = levene(*status_group)
print(f"Prueba de Levene: estadístico = {levene_stat}, p-value = {levene_p_value}")
Prueba de Levene: estadístico = 0.3238202814700971, p-value = 0.8988688535412217
En este caso sí tenemos Homocedasticidad, debido a que el p-value es mucho más mayor que 0.05.
De todas formas al no tener normalidad debemos de usar Kruskall-Wallis.
#Kruskall-Wallis para cada categoria de Marital_Status
group1 = df_2[df_2['Marital_Status'] == marital_order[0]]['Total_Spend']
group2 = df_2[df_2['Marital_Status'] == marital_order[1]]['Total_Spend']
group3 = df_2[df_2['Marital_Status'] == marital_order[2]]['Total_Spend']
group4 = df_2[df_2['Marital_Status'] == marital_order[3]]['Total_Spend']
group5 = df_2[df_2['Marital_Status'] == marital_order[4]]['Total_Spend']
group6 = df_2[df_2['Marital_Status'] == marital_order[5]]['Total_Spend']
stat, p_value = stats.kruskal(group1, group2, group3, group4, group5, group6)
print(f'Estadístico de Kruskal-Wallis: {stat}')
print(f'Valor p: {p_value}')
if p_value < 0.05:
print("Hay diferencias significativas entre los grupos.")
else:
print("No hay diferencias significativas entre los grupos.")
Estadístico de Kruskal-Wallis: 7.370315136436014
Valor p: 0.1945237547896254
No hay diferencias significativas entre los grupos.
Al observar los resultados del análisis mediante Kruskal-Wallis por Estado Marital, concluimos que no existen diferencias significativas en el gasto total entre los distintos grupos. Esto significa que el estado civil (Marital_Status) no tiene un impacto estadísticamente relevante en el comportamiento de gasto de las personas, según los datos analizados.
En otras palabras, las diferencias de gasto entre las categorías de estado civil (incluso después de una posible recategorización) no son lo suficientemente marcadas como para considerarse significativas. Por lo tanto, desde una perspectiva estadística, el estado civil no es un factor determinante a la hora de segmentar o analizar el comportamiento de gasto de los clientes.
5.2. Cantidad de hijos
Normalidad
# Crear una nueva columna 'Children_Category' categorizando el número de hijos
df_2['Children_Category'] = df_2['Children_Count'].astype(str)
cantidad_hijos = df_2['Children_Category'].unique().tolist()
#Prueba de Kolmogorov (Normalidad)
for hijos in cantidad_hijos:
group_data = df_2[df_2['Children_Category'] == hijos]['Total_Spend']
ks_stat, ks_p_value = kstest(group_data, 'norm')
print(f"KS para {edu} (Total_Spend): estadístico = {ks_stat}, p-value = {ks_p_value}")
KS para PhD (Total_Spend): estadístico = 0.9999999990134123, p-value = 0.0
KS para PhD (Total_Spend): estadístico = 1.0, p-value = 0.0
KS para PhD (Total_Spend): estadístico = 0.9999997133484281, p-value = 0.0
KS para PhD (Total_Spend): estadístico = 0.9999999999999993, p-value = 0.0
RESULTADOS: NO PRESENTA NORMALIDAD
Homocedasticidad
# Realizamos la prueba de Levene para homocedasticidad (Hijos)
status_group = [df_2[df_2['Children_Category'] == hijos]['Total_Spend'] for hijos in cantidad_hijos]
levene_stat, levene_p_value = levene(*status_group)
print(f"Prueba de Levene: estadístico = {levene_stat}, p-value = {levene_p_value}")
Prueba de Levene: estadístico = 82.76650024401404, p-value = 8.910410679935122e-51
PRESENTA HETEROCEDASTICIDAD
Kruskal-Wallis
# Crear los grupos por el número de hijos
group0 = df_2[df_2['Children_Category'] == cantidad_hijos[0]]['Total_Spend']
group1 = df_2[df_2['Children_Category'] == cantidad_hijos[1]]['Total_Spend']
group2 = df_2[df_2['Children_Category'] == cantidad_hijos[2]]['Total_Spend']
group3 = df_2[df_2['Children_Category'] == cantidad_hijos[3]]['Total_Spend']
# Realizar la prueba de Kruskal-Wallis
stat, p_value = stats.kruskal(group0, group1, group2, group3)
# Imprimir los resultados
print(f'Estadístico de Kruskal-Wallis: {stat}')
print(f'Valor p: {p_value}')
if p_value < 0.05:
print("Hay diferencias significativas entre los grupos.")
else:
print("No hay diferencias significativas entre los grupos.")
Estadístico de Kruskal-Wallis: 548.3466590214872
Valor p: 1.5859643569958945e-118
Hay diferencias significativas entre los grupos.
Estadístico de Kruskal-Wallis: 548.35 (es un valor alto, lo que indica una diferencia considerable entre los grupos).
Valor p: 1.59e-118, que es mucho menor que 0.05, lo que confirma que hay diferencias significativas entre los grupos con diferentes números de hijos.
Prueba Dunn
# Crear una lista de grupos para la prueba de Dunn
groups = [group0, group1, group2, group3]
# Aplicar la prueba de Dunn para comparar todos los pares de grupos
dunn_result = sp.posthoc_dunn(groups, p_adjust='bonferroni')
#dunn_result = sp.posthoc_dunn(df_2, val_col='Total_Spend', group_col='Children_Category', p_adjust='bonferroni')
# Mostrar los resultados
dunn_result.round(5) #Se redondeo para evitar valores con muchos decimales
Los grupos con 1 hijo y 3 hijos no tienen diferencias significativas en su gasto total (p = 1.0), lo que sugiere que podrían ser agrupados para ciertas campañas o promociones, ya que su comportamiento de gasto es similar.
En todos los demás casos, los grupos tienen diferencias significativas en su gasto total, lo que indica que el número de hijos tiene un impacto considerable en el comportamiento de gasto.
Podemos segmentar las personas en función del número de hijos, creando campañas específicas para aquellos con 1 y 3 hijos, y otras campañas para los grupos con 0, 2 y 3 hijos según su gasto y necesidades específicas.
Veamos el gasto promedio por cantidad de hijos.
# Calcular el gasto promedio por número de hijos
gasto_promedio_hijos = df_2.groupby('Children_Category')['Total_Spend'].mean().reset_index()
# Mostrar el gasto promedio por grupo
gasto_promedio_hijos
Conlusión para la segmentación
-
Segmentación con comportamiento de gasto similares:
- Los clientes con 1 o 3 hijos **presentan patrones de gasto muy similares. Esto sugiere que **una misma campaña podría ser efectiva para ambos grupos, optimizando recursos y estrategias de marketing.
-
Segmentos con comportamiento de gasto diferentes:
- Los clientes con 0, 2 y 3 hijos tienen patrones de gasto significativamente distintos entre sí. Por lo tanto, es recomendable mantener campañas separadas para estos segmentos, diseñando promociones específicas que respondan a las características únicas de cada grupo..
Nota clave:
Aunque los datos de gasto promedio entre los clientes con 2 y 3 hijos podrían parecer similares a simple vista, la estadística nos confirma que sus diferencias son significativas. Este hallazgo resalta la importancia de utilizar herramientas estadísticas para tomar decisiones informadas y diseñar estrategias basadas en evidencia sólida en lugar de suposiciones visuales o intuitivas.
La estadística no solo es una herramienta técnica, sino también un aliado estratégico para maximizar el impacto de las campañas de marketing y aumentar la rentabilidad.
6. Conclusiones Generales
- Importancia de la estadística:
Este análisis resalta la importancia de instrumentos estadísticos, tales como Kolmogorov-Smirnov, Levene, Kruskal-Wallis y la prueba post-hoc de Dunn, para corroborar variaciones importantes en los datos. Nos brindan la posibilidad de superar las percepciones visuales y asegurar que nuestras decisiones se fundamenten en pruebas fiables.
-
Segmentación efectiva basada en patrones de gasto:
- El grado de educación tiene un impacto considerable en el gasto total. Los clientes con educación básica muestran una conducta de consumo diferente a la de los con educación superior, lo que facilita la creación de campañas orientadas a cada sector.
- El análisis por número de hijos mostró diferencias notables entre los grupos. Es factible reunir a los clientes con 1 o 3 hijos, mientras que los demás grupos deben ser tratados de manera individual.
- El estado de matrimonio no evidenció variaciones importantes en el gasto, lo que sugiere que este elemento no es crucial para la segmentación en esta situación.
Decisiones basadas en evidencia:
Con este enfoque estadístico, se pueden evitar errores al interpretar patrones en los datos, lo que garantiza que los recursos y estrategias se inviertan de manera más efectiva.
7. Recomendaciones finales
-
Campañas dirigidas según nivel educativo:
- Personalizar estrategias para el grupo con educación básica.
- Unificar campañas para clientes con educación superior (Graduation, Master, PhD).
-
Segmentar según cantidad de hijos:
- Agrupar a los clientes con 1 o 3 hijos en una campaña conjunta.
- Diseñar estrategias separadas para los grupos con 0 y 2 hijos.
-
Monitorear y ajustar:
- Analizar el rendimiento de las campañas para realizar mejoras continuas.
-
Explorar más variables:
- Ampliar el análisis con otros factores como ingresos o antigüedad del cliente para identificar nuevas oportunidades de segmentación.
8. Conclusiones Finales
La estadística no solo es una herramienta poderosa para tomar decisiones informadas, sino que también es un proceso continuo. En marketing, los datos y las tendencias evolucionan constantemente, lo que significa que siempre hay nuevas oportunidades para segmentar mejor a los clientes y adaptar las estrategias a las necesidades cambiantes.
Recuerda que la clave está en no solo realizar un análisis una vez, sino en realizarlo de manera iterativa, ajustando las estrategias a medida que los datos se actualizan y mejoran. Al hacerlo, puedes mantener tu enfoque de marketing y otros más, siempre alineado con lo que realmente importa para tus clientes, lo que te permitirá tomar decisiones aún más confiables y efectivas.
La estadística es tu aliada para mejorar los resultados: úsala de manera dinámica y continua para tomar decisiones cada vez más confiables y efectivas.
Si crees que se puedan incluir mejoras o alguna parte del código no te funciona, hazmelo saber, te ayudaré con gusto :).
Si los datos te confunden, recuerda: todos somos normales… hasta que aparece un outlier.
Edgar Cajusol - Data Scientist - Creando impacto un modelo a la vez.
https://www.linkedin.com/in/edgarcajusol/
Top comments (0)