cómo las matemáticas pueden resolver tantos problemas en el mundo real. Cuando estaba en la escuela primaria, ciertamente no lo veía de esa manera. Por cierto, nunca odié las matemáticas y tampoco tuve problemas para aprender la mayoría de los conceptos básicos.
Sin embargo, confieso que para la mayoría de las clases más allá de la aritmética clásica, solía pensar: “nunca usaré eso para nada en mi vida”.
Aunque eran otros tiempos. No había Internet, ni ciencia de datos, y las computadoras apenas existían. Pero el tiempo pasa. ¡La vida pasa y veremos el día en que resolveremos importantes problemas comerciales con las viejas matemáticas!
En esta publicación, usaremos la famosa regresión lineal para un problema diferente: predecir la pérdida de clientes.
Regresión lineal vs abandono
La pérdida de clientes rara vez ocurre de la noche a la mañana. En muchos casos, los clientes reducirán gradualmente su frecuencia de compra antes de detenerla por completo. Algunos llaman a eso agitación silenciosa [1].
La predicción de la deserción se puede realizar con los modelos de deserción tradicionales, que (1) requieren datos de deserción etiquetados; (2) a veces son complejos de explicar; (3) detectar la deserción después de que ya haya ocurrido.
Por otro lado, este proyecto muestra una solución diferente, respondiendo a una pregunta más sencilla:
¿Es este cliente?
¿Ralentizando las compras?
Esta pregunta se responde con la siguiente lógica.
Utilizamos tendencias de compra mensuales y regresión lineal para medir el impulso del cliente a lo largo del tiempo. Si el cliente continúa aumentando sus gastos, el monto sumado crecerá con el tiempo, lo que generará una tendencia al alza (o una pendiente positiva en una regresión lineal, por así decirlo). Lo contrario también es cierto. Los montos de transacciones más bajos se sumarán a una tendencia bajista.
Analicemos la lógica en pequeños pasos y comprendamos qué haremos con los datos:
Agregar transacciones de clientes por mes Crear un índice de tiempo continuo (p. ej., 1, 2, 3…n) Completar los meses faltantes con cero compras Ajustar una línea de regresión lineal Usar la pendiente (convertida a grados) para cuantificar el comportamiento de compra Evaluación: Una pendiente negativa indica un compromiso decreciente. Una pendiente positiva indica un compromiso creciente.
Bueno, pasemos a continuación a la implementación.
Código
Lo primero es importar algunos módulos a una sesión de Python.
# Importaciones importar scipy.stats como estadísticas importar matplotlib.pyplot como plt importar numpy como np importar pandas como pd
Luego, generaremos algunos datos que simulan las transacciones de algunos clientes. Puedes ver el código completo en este repositorio de GitHub. El conjunto de datos generado incluye las columnas id_cliente, fecha_transacción y importe_total, y se verá como en la siguiente imagen.
Ahora crearemos una nueva columna que extraiga el mes de la fecha, para que nos resulte más fácil agrupar los datos más adelante.
# Crear nueva columna mes df[‘mth’] = gl[‘transaction_date’].dt.month # Agrupar clientes por mes df_group = ( df .groupby([‘mth’,’customer_id’])
[‘total_amt’]
.sum() .reset_index() )
Aquí está el resultado.
Si comprobamos rápidamente si hay clientes que no han realizado una transacción cada mes, encontraremos algunos casos.
Eso nos lleva al siguiente punto. Tenemos que asegurarnos de que, si el cliente no tiene al menos una compra al mes, entonces tenemos que sumar ese mes con un gasto de $0.
Construyamos una función que pueda hacer eso y también calculemos la pendiente de la tendencia de compra del cliente.
Esta función parece enorme, pero la repasaremos en partes más pequeñas. Hagamos esto.
Filtre los datos de un cliente determinado utilizando el método Pandas query(). Haz un grupo rápido y comprueba si el cliente tiene al menos una compra por cada mes. De lo contrario, agregaremos el mes faltante con un gasto de $0. Implementé esto fusionando un marco de datos temporal con los 12 meses y $0 con los datos originales. Después de la combinación de meses, los períodos que faltan serán filas con NaN para la columna de datos original, que se pueden completar con $0. Luego, normalizamos los ejes. Recuerde que el eje X es un índice del 1 al 12, pero el eje Y es el monto del gasto, en miles de dólares. Entonces, para evitar distorsiones en nuestra pendiente, normalizamos todo a la misma escala, entre 0 y 1. Para eso, usamos la función personalizada min_max_standardize. A continuación, podemos trazar la regresión utilizando otra función personalizada. Luego calcularemos la pendiente, que es el primer resultado devuelto por la función scipy.linregress(). Finalmente, para calcular el ángulo de la pendiente en grados apelaremos a la matemática pura, utilizando el concepto de arco tangente para calcular el ángulo entre el eje X y la recta de regresión lineal de la pendiente. En Python, simplemente use las funciones np.arctan() y np. Degrees() de numpy.
# Estandarizar los datos def min_max_standardize(vals): return (vals – np.min(vals)) / (np.max(vals) – np.min(vals)) #———— # Función rápida para trazar la regresión def plot_regression(x,y, cust): plt.scatter(x,y, color = ‘gray’) plt.plot(x, stats.linregress(x,y).slope*np.array(x) + stats.linregress(x,y).intercept, color = ‘red’, linestyle=’–‘) plt.suptitle(“Pendiente de la regresión lineal [Expenses x Time]”) plt.title(f”Cliente {cust} | Pendiente: {np.grados(np.arctan(stats.linregress(x,y).slope)):.0f} grados. Positivo = Comprar más | Negativo = Comprar menos”, tamaño=9, color=’gris’) plt.show() #—– def get_trend_grados(cliente, plot=False): # Filtrar los datos one_customer = df.query(‘customer_id == @customer’) one_customer = one_customer.groupby(‘mth’).total_amt.sum().reset_index().rename(columns={‘mth’:’period_idx’}) # Compruebe si todos los meses están en los datos cnt = one_customer.groupby(‘period_idx’).period_idx.nunique().sum() # De lo contrario, agregue 0 a los meses sin transacciones si cnt < 12: # Cree un DataFrame con los 12 meses all_months = pd.DataFrame({'period_idx': range(1, 13), 'total_amt': 0}) # Fusione con los datos existentes de one_customer # Utilice la combinación 'derecha' para mantener los 12 meses de 'all_months' y complete el total_amt faltante. = pd.merge(all_months, one_customer, on='period_idx', how='left', suffixes=('_all', '')) # Combina las columnas total_amt, prefiriendo los datos reales sobre el 0 de all_months one_customer['total_amt'] = un_cliente['total_amt'].fillna(un_cliente['total_amt_all']) # Suelte la columna temporal _all si existe one_customer = one_customer.drop(columns=['total_amt_all']) # Ordenar por period_idx para garantizar el orden correcto one_customer = one_customer.sort_values(by='period_idx').reset_index(drop=True) # Estandarización mínima máxima X = min_max_standardize(one_customer['period_idx']) y = min_max_standardize(un_cliente['total_amt']) # Trazar si trazar: plot_regression(X,y, cliente) # Calcular pendiente pendiente = stats.linregress(X,y)[0] # Calcular ángulo grados ángulo = np.arctan(pendiente) ángulo = np.grados(ángulo) ángulo de retorno
Excelente. Es hora de poner a prueba esta función. Consigamos dos clientes:
C_014. Este es un cliente con tendencia alcista que compra más con el tiempo. # Ejemplo de cliente fuerte get_trend_titles(‘C_014’, plot=True)
El gráfico que produce muestra la tendencia. Observamos que, aunque hay algunos meses más débiles en el medio, en general los montos tienden a aumentar a medida que pasa el tiempo.
La tendencia es de 32 grados, por lo que apunta hacia arriba, lo que indica una relación sólida con este cliente.
C_003. Este es un cliente con tendencia bajista que compra menos con el tiempo. # Ejemplo de cliente que deja de comprar get_trend_titles(‘C_003’, plot=True)
Aquí, los gastos a lo largo de los meses están disminuyendo claramente, lo que hace que la pendiente de esta curva apunte hacia abajo. La línea tiene 29 grados negativos, lo que indica que este cliente se está alejando de la marca y, por lo tanto, necesita ser estimulado para regresar.
Antes de ir
Bueno, eso es todo. Este proyecto demuestra un enfoque simple e interpretable para detectar un comportamiento de compra decreciente de los clientes mediante regresión lineal.
En lugar de depender de modelos complejos de abandono, analizamos las tendencias de compra a lo largo del tiempo para identificar cuándo los clientes se están desconectando lentamente.
Este modelo simple puede darnos una gran noción de hacia dónde se dirige el cliente, si es una mejor relación con la marca o se aleja de ella.
Ciertamente, con otros datos del negocio, es posible mejorar esta lógica y aplicar un umbral ajustado e identificar rápidamente a los posibles abandonos cada mes, en función de datos anteriores.
Antes de terminar, me gustaría dar el crédito adecuado a la publicación original que me inspiró a aprender más sobre esta implementación. Es un post de Matheus da Rocha que podéis encontrar aquí, en este enlace.
Finalmente, encuentre más sobre mí en mi sitio web.
https://gustavorsantos.me
Repositorio GitHub
Aquí encontrará el código completo y la documentación.
https://github.com/gurezende/Linear-Regression-Churn/tree/main
Referencias
[1. Forbes] https://www.forbes.com/councils/forbesbusinesscouncil/2023/09/15/is-silent-churn-killing-your-business-four-indicators-to-monitor
[2. Numpy Arctan] https://numpy.org/doc/2.1/reference/generated/numpy.arctan.html
[3. Arctan Explanation] https://www.cuemath.com/trigonometry/arctan/
[4. Numpy Degrees] https://numpy.org/doc/2.1/reference/generated/numpy.titles.html
[5. Scipy Lineregress] https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.linregress.html