Saltar al contenido principal

Introducción a la segmentación de clientes en Python

En este tutorial aprenderás a implementar la segmentación de clientes con análisis RFM (Recency, Frequency, Monetary) desde cero en Python.
· 8 min leer

Explora con IA

En el sector retail, las cadenas de hipermercados generan una cantidad de datos enorme. Estos datos se producen a diario en todas las tiendas. Esta base de datos tan extensa de transacciones de clientes debe analizarse para diseñar estrategias rentables.

Cada cliente tiene necesidades distintas. A medida que crece la base de clientes y el volumen de transacciones, no es fácil comprender lo que necesita cada uno. Identificar a los clientes con mayor potencial puede mejorar las campañas de marketing y, en última instancia, aumentar las ventas. La segmentación ayuda a agrupar a los clientes en distintos segmentos para poder abordarlos mejor.

¿Qué es la segmentación de clientes?

La segmentación de clientes es un método para dividir a los clientes en grupos o clústeres en función de características comunes. En el modelo B2C, la investigación de mercado puede segmentar clientes según características demográficas como ocupación, género, edad, ubicación y estado civil; características psicográficas como clase social, estilo de vida y personalidad; y características de comportamiento como gasto, hábitos de consumo, uso de productos/servicios y compras anteriores. En el modelo B2B, puede basarse en características de la empresa como tamaño, tipo de industria y ubicación.

chart

Por qué necesitas segmentar a tus clientes

  • Ayuda a identificar a los clientes con mayor potencial.
  • Permite a los responsables comunicarse con facilidad con un grupo objetivo.
  • Facilita la elección del mejor canal para llegar al segmento objetivo.
  • Mejora la calidad del servicio, la fidelidad y la retención.
  • Mejora la relación con el cliente al comprender mejor las necesidades de cada segmento.
  • Abre oportunidades de upselling y cross-selling.
  • Ayuda a diseñar ofertas especiales para clientes objetivo y animarles a comprar más.
  • Permite a las empresas llevar la delantera frente a la competencia.
  • Ayuda a identificar nuevos productos que podrían interesar a los clientes.

Tipos de segmentación

types of segmentation

Segmentación de clientes con análisis RFM

El análisis RFM (Recency, Frequency, Monetary) es un enfoque basado en el comportamiento que agrupa a los clientes en segmentos. Los agrupa según sus transacciones de compra anteriores: cuán reciente, con qué frecuencia y cuánto ha comprado un cliente. RFM clasifica a los clientes en distintos grupos para poder darles un mejor servicio. Ayuda a los responsables a identificar clientes con potencial para hacer el negocio más rentable. Por ejemplo, puede haber clientes que gastan mucho, pero ¿y si solo han comprado una vez o hace mucho? ¿Compran con frecuencia nuestros productos? Además, ayuda a ejecutar campañas promocionales eficaces y personalizadas.

  • Recency (R): ¿quién ha comprado recientemente? Número de días desde la última compra (menor recencia).
  • Frequency (F): ¿quién compra con frecuencia? Es el número total de compras (alta frecuencia).
  • Monetary value (M): ¿quién gasta más? Es el total de dinero que ha gastado el cliente (alto valor monetario).

Aquí, cada una de las tres variables (Recency, Frequency y Monetary) se divide en cuatro grupos iguales, lo que crea 64 (4x4x4) segmentos de clientes diferentes.

Pasos del análisis RFM (Recency, Frequency, Monetary):

  1. Calcular los valores de Recency, Frequency y Monetary para cada cliente.
  2. Asignar los valores de segmento (bins) a la tabla RFM usando cuartiles.
  3. Concatenar la puntuación RFM del cliente en una sola columna y ordenarla en orden ascendente.

1. Calcula los valores de Recency, Frequency y Monetary para cada cliente.

Recency, Frequency, Monetary values

2. Añade los valores de segmento a la tabla RFM usando cuartiles.

segment bin values on RFM table

3. Concatena todas las puntuaciones en una sola columna (RFM_Score).

all scores in single column

Identifica segmentos de clientes potenciales con RFM en Python

Importar las bibliotecas necesarias

#import modules
import pandas as pd # for dataframes
import matplotlib.pyplot as plt # for plotting graphs
import seaborn as sns # for plotting graphs
import datetime as dt

Cargar el conjunto de datos

Primero vamos a cargar el dataset de HR necesario con la función read CSV de pandas. Puedes descargar los datos desde este enlace.

data = pd.read_excel("Online_Retail.xlsx")
data.head()
dataset 1
data.tail()
dataset 2
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 541909 entries, 0 to 541908
Data columns (total 8 columns):
InvoiceNo      541909 non-null object
StockCode      541909 non-null object
Description    540455 non-null object
Quantity       541909 non-null int64
InvoiceDate    541909 non-null datetime64[ns]
UnitPrice      541909 non-null float64
CustomerID     406829 non-null float64
Country        541909 non-null object
dtypes: datetime64[ns](1), float64(2), int64(1), object(4)
memory usage: 33.1+ MB
data= data[pd.notnull(data['CustomerID'])]

Eliminar duplicados

A veces el dataset viene desordenado. Puede haber duplicados que distorsionen el análisis. En python, pandas ofrece la función drop_duplicates(), que elimina los registros repetidos o duplicados.

filtered_data=data[['Country','CustomerID']].drop_duplicates()

Vamos con algunos insights

#Top ten country's customer
filtered_data.Country.value_counts()[:10].plot(kind='bar')
<matplotlib.axes._subplots.AxesSubplot at 0x7fd81725dfd0>
data insights

En el dataset proporcionado, se observa que la mayoría de clientes son del "United Kingdom". Por tanto, puedes filtrar los datos para clientes del United Kingdom.

uk_data=data[data.Country=='United Kingdom']
uk_data.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 361878 entries, 0 to 541893
Data columns (total 8 columns):
InvoiceNo      361878 non-null object
StockCode      361878 non-null object
Description    361878 non-null object
Quantity       361878 non-null int64
InvoiceDate    361878 non-null datetime64[ns]
UnitPrice      361878 non-null float64
CustomerID     361878 non-null float64
Country        361878 non-null object
dtypes: datetime64[ns](1), float64(2), int64(1), object(4)
memory usage: 24.8+ MB

La función describe() de pandas es muy útil para obtener estadísticas descriptivas. Devuelve el recuento, media, desviación estándar, valores mínimo y máximo, y los cuantiles de los datos.

uk_data.describe()
 QuantityUnitPriceCustomerID
count361878.000000361878.000000361878.000000
mean11.0770293.25600715547.871368
std263.12926670.6547311594.402590
min-80995.0000000.00000012346.000000
25%2.0000001.25000014194.000000
50%4.0000001.95000015514.000000
75%12.0000003.75000016931.000000
max80995.00000038970.00000018287.000000

Aquí se observa que algunos clientes han realizado pedidos con cantidad negativa, lo cual no es posible. Por tanto, filtra Quantity para que sea mayor que cero.

uk_data = uk_data[(uk_data['Quantity']>0)]
In: # Change the name of columns
rfm.columns=['monetary','frequency','recency']
uk_data.info() 
<class 'pandas.core.frame.DataFrame'>
Int64Index: 354345 entries, 0 to 541893
Data columns (total 8 columns):
InvoiceNo      354345 non-null object
StockCode      354345 non-null object
Description    354345 non-null object
Quantity       354345 non-null int64
InvoiceDate    354345 non-null datetime64[ns]
UnitPrice      354345 non-null float64
CustomerID     354345 non-null float64
Country        354345 non-null object
dtypes: datetime64[ns](1), float64(2), int64(1), object(4)
memory usage: 24.3+ MB

Filtrar las columnas necesarias

Aquí vas a filtrar las columnas imprescindibles para el análisis RFM. Solo necesitas cinco: CustomerID, InvoiceDate, InvoiceNo, Quantity y UnitPrice. CustomerID identifica de forma única a cada cliente; InvoiceDate te permite calcular la recencia; InvoiceNo te ayuda a contar cuántas transacciones se han realizado (frecuencia). La cantidad comprada en cada transacción y el precio unitario de cada artículo te permiten calcular el importe total comprado.

uk_data=uk_data[['CustomerID','InvoiceDate','InvoiceNo','Quantity','UnitPrice']]
uk_data['TotalPrice'] = uk_data['Quantity'] * uk_data['UnitPrice']
uk_data['InvoiceDate'].min(),uk_data['InvoiceDate'].max()
(Timestamp('2010-12-01 08:26:00'), Timestamp('2011-12-09 12:49:00'))
PRESENT = dt.datetime(2011,12,10)
uk_data['InvoiceDate'] = pd.to_datetime(uk_data['InvoiceDate'])
uk_data.head()
 CustomerIDInvoiceDateInvoiceNoQuantityUnitPriceTotalPrice
017850.02010-12-01 08:26:0053636562.5515.30
117850.02010-12-01 08:26:0053636563.3920.34
217850.02010-12-01 08:26:0053636582.7522.00
317850.02010-12-01 08:26:0053636563.3920.34
417850.02010-12-01 08:26:0053636563.3920.34

Análisis RFM

Aquí vas a realizar las siguientes operaciones:

  • Para Recency, calcula el número de días entre la fecha actual y la última compra de cada cliente.
  • Para Frequency, calcula el número de pedidos de cada cliente.
  • Para Monetary, calcula la suma del importe de compra de cada cliente.
rfm= uk_data.groupby('CustomerID').agg({'InvoiceDate': lambda date: (PRESENT - date.max()).days,
                                        'InvoiceNo': lambda num: len(num),
                                        'TotalPrice': lambda price: price.sum()})
rfm.columns
Index(['InvoiceDate', 'TotalPrice', 'InvoiceNo'], dtype='object')
# Change the name of columns rfm.columns=['recency', 'monetary', 'frequency'] 
rfm['recency'] = rfm['recency'].astype(int)
rfm.head()
 monetaryfrequencyrecency
CustomerID   
12346.032577183.601
12747.024196.01103
12748.0033719.734596
12749.034090.88199
12820.03942.3459

Cálculo de cuantiles para los valores RFM

Los clientes con menor recencia y mayor frecuencia y valor monetario se consideran los mejores.

qcut() es una función de discretización basada en cuantiles. Divide los datos en bins según los cuantiles de la muestra. Por ejemplo, 1000 valores en 4 cuantiles producirán un objeto categórico que indica a qué cuantil pertenece cada cliente.

rfm['r_quartile'] = pd.qcut(rfm['recency'], 4, ['1','2','3','4'])
rfm['f_quartile'] = pd.qcut(rfm['frequency'], 4, ['4','3','2','1'])
rfm['m_quartile'] = pd.qcut(rfm['monetary'], 4, ['4','3','2','1'])
rfm.head()
 monetaryfrequencyrecencyr_quartilef_quartilem_quartile
CustomerID      
12346.032577183.601111
12747.024196.01103414
12748.0033719.734596414
12749.034090.88199414
12820.03942.3459324

Interpretación de resultados RFM

Combina los tres cuartiles (r_quartile, f_quartile, m_quartile) en una sola columna. Este rango te ayudará a segmentar mejor a tus clientes.

rfm['RFM_Score'] = rfm.r_quartile.astype(str)+ rfm.f_quartile.astype(str) + rfm.m_quartile.astype(str)
rfm.head()
 monetaryfrequencyrecencyr_quartilef_quartilem_quartileRFM_Score
CustomerID       
12346.032577183.601111111
12747.024196.01103414414
12748.0033719.734596414414
12749.034090.88199414414
12820.03942.3459324324
# Filter out Top/Best cusotmers
rfm[rfm['RFM_Score']=='111'].sort_values('monetary', ascending=False).head()
 monetaryfrequencyrecencyr_quartilef_quartilem_quartileRFM_Score
CustomerID       
16754.03722002.42111111
12346.032577183.61111111
15749.023544534.310111111
16698.02261998.05111111
13135.01963096.01111111

Conclusión

¡Enhorabuena, has llegado al final de este tutorial!

En este tutorial has visto en detalle la segmentación de clientes: qué es, por qué la necesitas, los tipos de segmentación, el análisis RFM y cómo implementarlo desde cero en python. También repasaste conceptos básicos de pandas como la gestión de duplicados, groupby y qcut() para crear bins basados en cuantiles de muestra.

Esperamos que ahora puedas aplicar el modelado de temas para analizar tus propios datasets. ¡Gracias por leer!

Si quieres aprender más sobre Python, haz el curso gratuito de DataCamp Intro to Python for Data Science.

Temas

Relacionado

Tutorial

Funciones en Python: cómo llamar y escribir funciones