![Compra on-line](https://www.analyticslane.com/storage/2018/05/ecommerce-2140603_1920.jpg)
El concepto de valor de ciclo de vida de cliente (CLV) se explico en una entrada anterior. Uno de los parámetros necesarios para obtener un valor correcto del CLV es la tasa de retención de los clientes. Este valor nos indica el porcentaje de clientes que continúan activos después de un periodo de tiempo.
Para un análisis básico se puede asumir que el valor de la tasa de retención es el mismo y constante para todos los clientes. Aunque realmente este depende de factores demográficos (edad, ubicación geográfica, profesión, …) y del comportamiento (recencia, frecuencia, …). En esta entrada veremos una forma de estimar este parámetro en base a los datos de comportamiento.
La tasa de retención en el CLV
Existen diferentes expresiones para calcular el CLV. Posiblemente una de las más utilizadas es la que se explico en la entrada que se dedico con anterioridad al concepto:
CLV = \sum_{t=0}^n \frac{b_t}{(1 + r)^t}donde n son los años que dura la relación, b_t es el beneficio obtenido en al año t y r es la tasa de descuento. El beneficio de un cliente en el año t se puede asumir que es
b_t = p r^tdonde p son los ingresos anuales y r es la tasa de retención del cliente.
![Feliz Navidad y próspero Año Nuevo 2025](https://www.analyticslane.com/storage/2018/05/sunset-3120484_1920-300x169.jpg)
La tasa de retención de los clientes se puede estimar realizando una regresión frente a los factores de comportamiento. Simplemente se ha de obtener los datos de comportamiento y los clientes que se mantienen activos después de un periodo. Con esto se puede entrenar un modelo logístico que nos indique la probabilidad de mantenerse activo.
La tasa de retención se calculará a partir de los valores de la recencia, frecuencia y valor monetario. Para esto se utilizarán los datos de CDNow que se pueden encontrar en http://www.brucehardie.com/datasets/
Conjunto de datos CDNow
Uno de los conjuntos de datos más utilizados para desarrollar modelos de CLV es el de la tienda de música online CDNow. En este conjunto se recoge el historial de compra de 23.570 clientes que realizaron una primera compra durante el el primer trimestre de 1997. El conjunto de datos contiene un total de 69.659 registros, correspondiente a compras realizadas entre enero de 1997 y finales de junio de 1998. En cada uno de los registros se tienen
- el id del cliente
- la fecha de la transacción
- el número de discos compactos adquiridos
- el valor monetario en dólares de la transacción.
Los primeros registros se muestran en la siguiente tabla:
ID | Date | Value |
1 | 1/1/97 | 11,77 |
2 | 12/1/97 | 12,00 |
2 | 12/1/97 | 77,00 |
3 | 2/1/97 | 20,76 |
3 | 30/3/97 | 20,76 |
En primer lugar, se ha de importar los datos del archivo. Para ello se utiliza el siguiente comando:
cdnow = pd.read_csv('CDNOW_master.txt', names=['ID', 'Date', 'CDs', 'Value'], header=None, delim_whitespace=True, dtype={'Date': object})
Una vez importados los datos se ha de convertir la fecha de texto a formato datetime
. Esto se consigue con el siguiente comando:
cdnow['Date'] = pd.to_datetime(cdnow['Date'], format='%Y%m%d')
Procesado de los datos
El conjunto de datos se va a dividir en dos, las compras realizadas entre el 1 de enero de 1997 y el 28 de febrero de 1998 se utilizarán para crear un modelo de comportamiento. El resto de los datos, los comprendidos entre el 1 marzo de 1998 y el 30 de abril del 1998, se utilizarán para identificar los clientes que continúan comprando en el siguiente periodo. En el primer subconjunto es necesario obtener la recencia, la frecuencia y el valor monetario promedio de los clientes. Para esto se utiliza el siguiente código:
def processData(cdnow, start, end): result = cdnow[(cdnow.Date >= start) & (cdnow.Date <= end)] frequency = result.groupby(["ID"]).agg(['count', 'sum']) frequency.reset_index(inplace=True) frequency.columns = ['ID', 'Frequency', 'Monetary'] frequency['Monetary'] = frequency['Monetary'] / frequency['Frequency'] result = pd.merge(result, frequency, on='ID') result = result.drop_duplicates('ID', keep='last') result['Recency'] = ((end - result['Date']) / np.timedelta64(1, 'M')).astype(int) result = result.drop('Date', 1) result = result.drop('Value', 1) return result
En esta función lo primero que se hace es seleccionar los datos entre las fechas indicadas. Posteriormente se agrupan los datos por ID obteniendo el número ocurrencias y el total del valor monetario total. Dado que es necesario obtener el valor monetario promedio, este se ha de dividir por la frecuencia. La recencia se obtiene seleccionado únicamente la última ocurrencia para cada ID y calculando el tiempo, en meses, desde la última compra hasta el final del periodo.
Finalmente, se eliminan los registros que no se van a utilizar, la fecha y el valor monetario original del registro. Los primeros registros de esta tabla son:
ID | Frequency | Monetary | Recency |
1 | 1 | 11,77 | 13 |
2 | 2 | 45,50 | 13 |
3 | 5 | 28,89 | 3 |
4 | 4 | 25,12 | 2 |
5 | 11 | 35,05 | 1 |
Esta tabla se ha de cruzar con los datos del posteriores para identificar los clientes que vuelve a comprar en los dos meses posteriores al periodo de entrenamiento. Esto se puede hacer con el siguiente código:
result = pd.merge(train, forecast[['ID', 'Frequency']], on='ID', how = 'left') result = result.rename(columns={'Frequency_x': 'Frequency', 'Frequency_y': 'Buy'}) result['Buy'] = result['Buy'].notnull()
A partir lo de lo queda la siguiente tabla
ID | Frequency | Monetary | Recency | Buy |
1 | 1 | 11,77 | 13 | False |
2 | 2 | 45,50 | 13 | False |
3 | 5 | 28,89 | 3 | False |
4 | 4 | 25,12 | 2 | False |
5 | 11 | 35,05 | 1 | False |
Primeros resultados
Con los datos obtenidos hasta ahora se puede hasta ahora se pude hacer un análisis para ver cómo afectan la recencia y la frecuencia a la probabilidad de compra de un cliente. Esto se puede observar en la siguiente gráfica en la que se muestra la probabilidad de compra frente a la recencia y a la frecuencia.
![Resultados CLV](https://www.analyticslane.com/storage/2018/05/valores_clv.png)
En estas gráficas se pueden comprobar lo que seria esperado. Los clientes con mayor recencia, los que han comprado hace poco, tiene mayor probabilidad de retención. Por otro lado, se observa lo contrario para la frecuencia, los que más veces han comprado tiene más posibilidades de continuar.
Modelado
Este conjunto de datos se puede utilizar para entrenar un modelo logístico. A partir del cual se podrá obtener la probabilidad de que un cliente con un perfil dado continúe activo en la tienda. Es decir, se va a obtener la ratio de retención. Esto se puede obtener mediante:
from sklearn.linear_model.logistic import LogisticRegression model = LogisticRegression().fit(result[['Recency', 'Frequency', 'Monetary']], result['Buy'])
Así para un tipo de cliente se puede obtener tanto la probabilidad de que un cliente realice una compra o no en el siguiente periodo. Para esto se utiliza el método predict_proba
.
p_buy = model.predict_proba(df)
Asumiendo que esta ratio se mantiene constante a lo largo del tiempo. Solamente es necesario definir una tasa de descuento y el número de periodos para obtener el CLV promedio de un perfil. A modo de ejemplo, un cliente con recencia igual a 2, frecuencia igual a 1 y valor monetario de 10 su CLV para los próximos 5 periodos será:
clv = 0 monetary = 10 discount = 0.10 period = 5 for period in range(1, period): clv += monetary * p_buy[0][1] / (1 + discount) ** period
Con lo que se obtienen un valor de 6,41 $ a valor presente.
Conclusiones
En esta entrada se ha realizado el cálculo CLV de los clientes utilizándose una regresión logística para estimar la tasa de retención. Ello implica que se asuma que esta tasa es constante a lo largo del tiempo. Lo que generalmente esto no es cierto. En una próxima entrada se verá el modelo BG / NBD en el que se tiene en cuenta que la ratio se reduce con el tiempo.
Deja una respuesta