Segmentación de clientes con RFM
En primer lugar, ¿qué es RFM?
RFM es un indicador clave que consta de tres métricas para comprender las relaciones actuales de los clientes con las empresas. El análisis RFM es una técnica basada en reglas, impulsada por datos y ampliamente utilizada para la segmentación de clientes con métricas de R ecency, F requency y Monetary utilizando los datos del cliente.
El análisis RFM se realiza para satisfacer mejor las necesidades de los diferentes tipos de clientes por separado. Los clientes se agrupan según sus hábitos de compra para que se puedan desarrollar estrategias comerciales únicas para estos grupos. Los tratamientos individuales pueden evitar la pérdida de clientes y garantizar que los clientes leales se mantengan así.
Tres factores clave:
La actualidad se refiere a la duración del tiempo de la última interacción con el cliente. El valor de antigüedad más pequeño corresponde a la última compra; así que cuanto más pequeño mejor. Los clientes más recientes son más valiosos.
Actualidad = Fecha del análisis — Fecha de la última compra
La frecuencia se refiere a la frecuencia con la que un cliente realiza una compra. Los clientes frecuentes son más valiosos.
Monetario se refiere al valor financiero que cada cliente gastó en esta empresa.
¿Cómo comparar estas métricas?
Estas métricas se convierten en puntuaciones para que sean del mismo tipo y puedan ser comparables entre sí. Esta conversión también puede llamarse estandarización. Los puntajes que provienen de las métricas se adjuntan entre sí y forman el puntaje RFM para cada cliente individual. Principalmente, los clientes se clasifican con respecto al valor que aportan a la empresa del 1 al 5.
Los puntajes de RFM pueden estar en un amplio rango, por lo tanto, se aplica un método en los puntajes de RFM para formar segmentos para que estos segmentos tengan información significativa.
Segmentación a través de puntuaciones RFM:
La segmentación se realiza comúnmente a través del gráfico 2-D que se muestra en la Tabla 1 . De esta manera, las puntuaciones de RFM tienen sentido. RFM Analysis puede ayudar a las empresas a conocer a sus clientes y mejorar sus estrategias de marketing en consecuencia.
Como se ve, la puntuación monetaria no está en el gráfico, ya que en el análisis de CRM, la frecuencia y la actualidad son más significativas que las monetarias. Cuando lo piensa, el análisis monetario de un cliente con pocas transacciones no es tan importante en comparación con los clientes frecuentes. Si bien el valor monetario no se representa explícitamente en el gráfico, sigue siendo un componente importante del análisis RFM y se utiliza para hacer suposiciones.
Resolviendo un problema de negocio a través de RFM:
Veamos cómo se aplican estos conceptos en un conjunto de datos del mundo real, qué información se puede extraer de los datos. Puede acceder al código completo en mi perfil de GitHub para una mejor demostración.
Durante un análisis de datos, hay ciertos pasos a seguir.
1. Problema comercial
Una empresa de comercio electrónico con sede en el Reino Unido quiere dividir a sus clientes en segmentos y definir estrategias de marketing de acuerdo con estos segmentos. Existe un conjunto de datos que consta de las ventas entre el 12/01/2009 y el 12/09/2011.
2. Comprender los datos
El conjunto de datos incluye 8 variables, a saber, factura, código de stock, descripción, cantidad, fecha de factura, precio, ID de cliente y país. Las facturas que comienzan con "C" son para transacciones canceladas. Para entender a lo que nos enfrentamos necesitamos echar un vistazo a los datos. El análisis se realizará para los años 2010–2011, sin embargo, también se puede utilizar para los años 2009–2010, ya que el proceso se generalizará al final.
Ajustes principales (importar las bibliotecas y configurar las preferencias de visualización de datos):
import datetime as dt
import pandas as pd
pd.set_option('display.max_columns', None) #to see all the columns
pd.set_option('display.float_format', lambda x: '%.3f' % x) #to have 3 decimal points
df_ = pd.read_excel("excel-file-destination.xlsx", sheet_name="Year 2010-2011")
df = df_.copy() #It takes time to read the file,thus a copy is taken after reading the file
#so we do not have to read the file and have to wait repeatedly thoughout the analysis
df.head() #unless specified otherwise, returns the first 5 rows of the dataset
df.shape #returns the number of the ows and columns
df.isnull().sum() #returns the number of null values in every column
Un gran conjunto de datos en cuestión con 541910 filas y 8 columnas. Pero, ¿debemos considerar todos los datos para el análisis?
Tenemos valores faltantes en la mayoría de las variables ID de cliente y Descripción. Esto significa que tendremos que eliminar las filas de ID de cliente que faltan, ya que el análisis es específico del cliente, los datos que faltan no brindan información.
Respondamos algunas preguntas:
# Number of unique products
df["Description"].nunique()
# Number of products appearing in invoices()
df["Description"].value_counts().head()
# Most ordered product (including quantities)
df.groupby("Description").agg({"Quantity": "sum"}).sort_values("Quantity", ascending=False).head()
# Number of unique invoices
df["Invoice"].nunique()
# Add a new column for TotalPrice
df["TotalPrice"] = df["Quantity"] * df["Price"]
# Find the total cost in every invoice
df.groupby("Invoice").agg({"TotalPrice": "sum"}).head()
# needed for monetary metric
La preparación de datos juega un papel importante en el análisis. Los datos deben manipularse de manera que se puedan hacer inferencias. Los problemas en este conjunto de datos y las soluciones se explican a continuación en el código.
df.shape # To observe the reducing number of rows as we make adjustments
df.isnull().sum() # Observed problem: Missing Customer ID data, needed to be erased
df.describe().T # Observed problem: Negative Quantitity values, no meaning, needed to be erased
df = df[(df['Quantity'] > 0)] # To solve Negative Quantitity values problem
df.dropna(inplace=True)
# To solve Missing Customer ID data problem
# Inplace makes the changes on dataset immediately without a need for assigning
df["Invoice"] = df["Invoice"].astype(str)
df = df[~df["Invoice"].str.contains("C", na=False)]
# Cancelled invoices do not need to be in the analysis, so they are erased.
# "~" means except this:
4. Cálculo de métricas de RFM
Hasta ahora, básicamente preparamos los datos para que podamos realizar un análisis RFM en ellos. Ahora, comencemos el análisis con el cálculo de las métricas. Dado que ya no vivimos en 2010-2011, necesitamos establecer una fecha en la que se realice el análisis. Para este propósito, busquemos la última fecha y decidamos un día cercano para realizar el análisis.
Luego, las operaciones se realizan en las columnas InvoiceDate, Invoice y TotalPrice y se agrupan por ID de cliente para obtener el marco de datos RFM que contiene métricas recientes, de frecuencia y monetarias, respectivamente.
df["InvoiceDate"].max() # latest date on data
today_date = dt.datetime(2011, 12, 11)
# added 2 days to last day to form today's date
# utilized datetime library so that today_date's datatype is datetime
type(today_date)
rfm = df.groupby('Customer ID').agg({'InvoiceDate': lambda InvoiceDate: (today_date - InvoiceDate.max()).days,
'Invoice': lambda Invoice: Invoice.nunique(),
'TotalPrice': lambda TotalPrice: TotalPrice.sum()})
# In order, Recency, Frequency, Monetary are found.
# Recency is the difference in the today's date and last purchase on Customer ID level.
# Frequency is the number of unique invoices that belongs to the same customer.
# Monetary is summation of total prices of the same customer, so we know how much each customer brings to the company.
rfm.head()
# check the data
rfm.columns = ['recency', 'frequency', 'monetary']
# change the column names
rfm.describe().T # to see if there is an unsual situation
rfm = rfm[rfm["monetary"] > 0]
# min monetary = 0 is unusual, so they are excluded.
rfm.shape
5. Cálculo de puntuaciones de RFM:
Al calcular los puntajes de RFM, lo primero que debe tener en cuenta es que los puntajes de actualidad se asignan al revés en comparación con la frecuencia y el dinero debido a sus significados.
rfm["recency_score"] = pd.qcut(rfm['recency'], 5, labels=[5, 4, 3, 2, 1])
# recency metrics divided 5 equal parts acoording to their sizes and
# labelled such a way that greatest recency got 1, the smallest recency got 5.
rfm["frequency_score"] = pd.qcut(rfm['frequency'].rank(method="first"), 5, labels=[1, 2, 3, 4, 5])
# the problem in frequency is some numbers are too repetitive that
# qcut can not label the same frequency number diffently
# rank method solves this problem by assigning the first comer number to first label.
rfm["monetary_score"] = pd.qcut(rfm['monetary'], 5, labels=[1, 2, 3, 4, 5])
rfm["RFM_SCORE"] = (rfm['recency_score'].astype(str) +
rfm['frequency_score'].astype(str))
# by RFM definition, string is created with recency and frequency score
# and formed final RFM Score
# monetary score is necessary for observation, but it is not used in forming RFM Score
rfm.describe().T
# newly created scores did not apper with describe function
# since they are strings and not integers
rfm[rfm["RFM_SCORE"] == "55"]
# champions
rfm[rfm["RFM_SCORE"] == "11"]
# hibernating
Para aumentar la legibilidad de la tabla, vamos a agregar lo que cada segmento significa para nosotros según la Tabla 1 .
RegEx (expresiones regulares) contiene coincidencias que se ajustan a un cierto patrón dentro de una serie. Esta es la parte en la que extraemos información de los datos.
# regex
# RFM Naming (Pattern Matching)
seg_map = {
r'[1-2][1-2]': 'hibernating',
r'[1-2][3-4]': 'at_Risk',
r'[1-2]5': 'cant_loose',
r'3[1-2]': 'about_to_sleep',
r'33': 'need_attention',
r'[3-4][4-5]': 'loyal_customers',
r'41': 'promising',
r'51': 'new_customers',
r'[4-5][2-3]': 'potential_loyalists',
r'5[4-5]': 'champions'
}
# Basically the R-F table is coded using regex.
rfm['segment'] = rfm['RFM_SCORE'].replace(seg_map, regex=True)
segment_analysis = rfm[["segment", "recency", "frequency", "monetary"]].groupby("segment").agg(["mean", "count"])
rfm[rfm["segment"] == "cant_loose"].head()
cant_loose_customers = rfm[rfm["segment"] == "cant_loose"].index
# A list of customers which the company should be more careful with is formed.
# This way, every segment of customers is accesible.
new_df = pd.DataFrame()
# Empty dataframe is formed
new_df["new_customer_id"] = rfm[rfm["segment"] == "new_customers"].index
new_df["new_customer_id"] = new_df["new_customer_id"].astype(int)
# To get rid of the decimals
new_df.to_csv("new_customers.csv")
rfm.to_csv("rfm.csv")
# Segment information is extracted into an excel file.
De acuerdo con principios básicos de programación como DRY (Don't Repeat Yourself), la funcionalización de todo este proceso es imprescindible. Por lo tanto, podemos usar esta función, por lo tanto, el Análisis RFM, en diferentes marcos de datos repetidamente.
Versión limpia de todos los datos anteriores escritos en la función a continuación en el nombre de create_rfm con la opción para crear un archivo csv.
def create_rfm(dataframe, csv=False):
PD: Muchas gracias por dedicar su tiempo a leer todo esto. Comparto a medida que aprendo, por lo que cada semana aparecerán nuevos artículos relacionados con la ciencia de datos. Espero que esta publicación también te ayude. No dude en dejar un comentario :) La mejor de las suertes en su propio viaje de ciencia de datos.
Conéctate conmigo en LinkedIn
Conéctate conmigo en Medium
Referencia:
- Vídeos de conferencias de Miuul

![¿Qué es una lista vinculada, de todos modos? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































