Quem me conhece sabe que eu acompanho com frequência a comunidade de Data Science Kaggle e principalmente o que a galera do Brasil anda aprontando por lá. Recentemente o André Sionek, Data Scientist na Olist divulgou aqui no LinkedIn que a empresa tornaria pública – com os devidos tratamentos para tornar os usuários em anônimos – mais de 100 mil transações realizadas entre 2016 e 2018.
Para realizar o RFM Analysis será utilizado este dataset. Contudo, o conceito é aplicável em outros conjuntos de dados. Conforme imagem abaixo, os dados da Olist são divididos em 8 tabelas que se conectam por meio de chaves – padrão de banco de dados relacional.
É possível notar que são inúmeras as possibilidades de análise. Contudo, para realizar a análise RFM, não será necessário explorar todo o conjunto de dados.
O que é RFM Analysis?
O RFM ou Recency, Frequency, Monetary Value é um método de análise que tem como objetivo classificar os usuários por meio de pontuações nos três principais pilares que nomeiam o método: dias desde que o usuário realizou a última transação, qual a frequência ou quantidade total de pedidos e o valor investido nas transações.
Com o método, é possível criar segmentos com o objetivo de otimizar a comunicação e melhorar o retorno sobre investimento. No item 4 falaremos um pouco mais sobre. Desta forma, o método consiste basicamente em 4 etapas:
- Preparar;
- Cortar;
- Categorizar;
- Comunicar. Aqui você também encontra algumas dicas 😉
1. Preparar
Começaremos primeiramente importando os módulos necessários para realizar a análise: Pandas e Datetime. Enquanto a primeira nos permite manipular com facilidade os datasets em Data Frames, a segunda nos permite manipular datas.
Um ponto importante é que necessitamos o valor total de receita investida por cada usuário. Para obter o valor total, será necessário relacionar três tabelas por meio de suas chaves únicas. Feito isso, multiplicaremos o preço do produto pela quantidade comprada em cada pedido.
import pandas as pd from datetime import datetime from datetime import timedelta #Leitura dos dados
customer = pd.read_csv(‘olist_customers_dataset.csv’)
orders = pd.read_csv(‘olist_orders_dataset.csv’)
order_items = pd.read_csv(‘olist_order_items_dataset.csv’)
#O .merge on=’chave’ é o responsável por conectar as tabelas
customer_orders = customer.merge(orders, on=’customer_id’)
customer_orders_items = customer_orders.merge(order_items, on=’order_id’)
#Aqui é criada uma nova coluna com o total
r_orders_items[‘total_spend’] = customer_orders_items[‘order_item_id’] * customer_orders_items[‘price’]
Abaixo realizaremos alguns filtros e pequenas transformações para facilitar a análise. Vale lembrar que estamos considerando as transações do dataset como se fossem de uma mesma empresa. Contudo, dado que temos a informação em uma coluna, seria possível também filtrar pelo ID do vendedor e realizar a análise apenas para este ID.
Para o exemplo, filtraremos apenas os pedidos que de fato constam como entregues. Porém, os outros status podem servir para uma análise posterior, com o fim de buscar alguma relação com os status.
#Aqui, consideraremos apenas os pedidos que de fato foram entregues customer_orders_items = customer_orders_items[customer_orders_items[‘order_status’] == ‘delivered’]
#Transformaremos a coluna em datetime para realizar contagens de dias customer_orders_items[‘order_purchase_timestamp’] = pd.to_datetime(customer_orders_items[‘order_purchase_timestamp’])
#Deixaremos apenas as colunas que são interessantes para a análise
df = customer_orders_items[[‘customer_unique_id’, ‘customer_id’, ‘order_purchase_timestamp’, ‘total_spend’]]
#Além de manter apenas as transações que ocorreram após 01/jan de 2018.
start_date = ‘2018-01-11’; end_date = datetime.today()
df = df[(df[‘order_purchase_timestamp’] > start_date) & (df[‘order_purchase_timestamp’] <= end_date)]
Feito isso, partiremos para a transformação das datas. A coluna de datas está no padrão 2000-01-11 00:00:01, contudo precisamos deste como uma contagem de dias. Para que seja possível realizar uma contagem de Recência, criaremos um snapshot. Este por sua vez terá a função de ser o ponto de partida da contagem. Visto que não queremos o início em 0 dias, adicionaremos 1 dia no snapshot.
O Snapshot é a data que desejamos considerar como final da contagem regressiva dos dias. Para que as transações ocorridas nesta data, subtraídas pelo snapshot, não seja igual a 0, adicionaremos um dia.
#Snapshot
snapshot_date = max(df.order_purchase_timestamp) + timedelta(days=1)
#Aqui entra o agrupamento descrito acima
dataolist = df.groupby([‘customer_unique_id’]).agg({ ‘order_purchase_timestamp’: lambda x: (snapshot_date – x.max()).days, ‘customer_id’: ‘nunique’, ‘total_spend’: ‘sum’})
#Renomeando apenas para facilitar o entendimento
dataolist.rename(columns = {‘order_purchase_timestamp’: ‘Recency’, ‘customer_id’: ‘Frequency’, ‘total_spend’: ‘MonetaryValue’}, inplace=True)
2. Cortar
Nesta etapa, é fundamental o conhecimento dos dados. Realizar uma análise descritiva se faz necessária. Para o exemplo, dividiremos as observações em três partes iguais tanto em Recency quanto em Monetary Value.
Em Frequency, foi identificado que muitos dos usuários compraram apenas uma vez. Sendo assim, cortaremos em 1, 2, 3 ou mais transações. Um ponto importante: quanto menor a Recency, maior deve ser o scoring atribuído a ela.
Obs: um outro método muito utilizado é a k-means clustering. Em breve, farei uma postagem utilizando esta abordagem, bem como identificar a quantidade ótima de clusters por meio do método elbow.
#Recency em quartis
r_labels = range(3, 0, -1)
r_quartiles = pd.qcut(dataolist[‘Recency’], 3, labels = r_labels) dataolist = dataolist.assign(R = r_quartiles.values)
#Frequency em 1, 2 e 3+
f_bin_edges = [0, 1, 2, dataolist[‘Frequency’].max()]
f_bin_names = [1, 2, 3]
dataolist[‘F’] = pd.cut(dataolist[‘Frequency’], f_bin_edges, labels=f_bin_names)
#Monetary Value em quartis
m_labels = range(1, 4)
m_quartiles = pd.qcut(dataolist[‘MonetaryValue’], 3, labels = m_labels) dataolist = dataolist.assign(M = m_quartiles.values)
Feito isso, teremos três colunas novas que correspondem a cada parte do RFM. Estes serão a base para o clustering.
3. Categorizar
Criaremos uma função para categorizar os clientes com base no scoring de cada coluna. Para este, dividiremos em 11 grupos diferentes. Aqui fica a seu critério decidir como realizar a classificação.
def segment_me(df):
if (df[‘R’] == 3) and (df[‘F’] == 3) and (df[‘M’] == 3):
return ‘Champions’
elif (df[‘R’] == 3) and (df[‘F’] == 1) and (df[‘M’] == 1):
return ‘Recent’
elif (df[‘R’] == 3) and (df[‘F’] <= 2) and (df[‘M’] <= 3):
return ‘Promising’
elif (df[‘R’] == 3) and (df[‘F’] >= 2) and (df[‘M’] >= 2):
return ‘Loyal’
elif (df[‘R’] == 2) and (df[‘F’] >= 2) and (df[‘M’] >= 2):
return ‘Potential’
elif (df[‘R’] == 2) and (df[‘F’] <= 2) and (df[‘M’] <= 3):
return ‘Attention’
elif (df[‘R’] == 1) and (df[‘F’] == 1) and (df[‘M’] <= 3):
return ‘lost’
elif (df[‘R’] == 1) and (df[‘F’] == 2) and (df[‘M’] <= 3):
return ‘About_Sleep’
elif (df[‘R’] == 1) and (df[‘F’] == 1) and (df[‘M’] <= 3):
return ‘At_risk’
elif (df[‘R’] == 1) and (df[‘F’] == 3) and (df[‘M’] == 3):
return ‘Cant_lose’
else:
#(df[‘R’] == 1) and (df[‘F’] <= 3) and (df[‘M’] <= 3)
return ‘Hibernating’
Para aplicar e verificar as descritivas de cada grupo é relativamente simples.
dataolist[‘General_Segment’] = dataolist.apply(segment_me, axis=1)
dataolist.groupby(‘General_Segment’).agg({ ‘Recency’: ‘mean’, ‘Frequency’: ‘mean’, ‘MonetaryValue’: [‘mean’,’count’] }).round(1)
Feito isso, podemos partir para a ativação dos grupos. Dado que temos agora os usuários categorizados, podemos cruzar o ID do usuário com outras informações correspondentes.
4. Comunicar
Um dos piores erros no marketing é a comunicação genérica. De fato, o usuário passa por diferentes etapas em sua jornada com uma marca. Os agrupamentos anteriores foram realizados justamente pensando na assertividade da comunicação com o cliente.
Champions – São os compradores campeões. Realizaram compras recentes, compram com frequência e investem muito. Você deve recompensá-los para que divulguem ainda mais o seu negócio.
Loyal – Usuários leais ao seu negócio, mas que não investem tanto quanto os Campeões, mas estão quase lá. Uma dica é engajar estes clientes e motivar o upsell.
Potential – São usuários recentes e que compraram mais de uma vez. Recomende novos produtos ou informe-os sobre o plano de fidelidade, por exemplo.
Promising – Clientes promissores. São recentes mas que ainda não investiram muito. Foque em campanhas de engajamento e ofereça descontos. Aproveite esse início para criar um vínculo com a sua marca.
Attention – Usuários que estão na média em ambos os scorings RFM. Ofertas por tempo limitado com foco em reativação é uma abordagem interessante.
About Sleep – Usuários que estão mais pra lá do que pra cá. Aqui as ações devem ter como foco a reconexão, como por exemplo, mote de sentimos a sua falta.
At risk – Clientes que eram bons, mas precisam ser resgatados. Uma dica é criar um conteúdo personalizado com base no histórico.
Cant Lose – Clientes que eram ótimos, e necessariamente precisam ser resgatados. O mote pode ser similar ao At risk, o objetivo é trazer eles de volta.
Hibernating – Clientes que investiram pouco e há muito tempo. Crie valor de marca por meio de ofertas e descontos.
Lost – Clientes que compraram e não voltaram mais. Tente resgatá-los, mas os esforços não devem ser concentrados neste grupo.
Dado que são grupos de clientes em estágios diferentes, analise os indicadores separadamente. Verifique a evolução de cada grupo, bem como as possíveis transições motivadas pelas campanhas. Com isso, fica mais fácil medir o real retorno do investimento e projetar mudanças nas ações. Assim como Avinash costuma dizer: “Você é o que você mede, então escolha os indicadores sabiamente”.
Ficou com dúvidas ou tem sugestões, coloque abaixo nos comentários. 🙂
Referências
towardsdatascience.com/apply-rfm-principles-to-cluster-customers-with-k-means-fef9bcc9ab16
clevertap.com/blog/rfm-analysis/
www.kaushik.net/avinash/rules-choosing-web-analytics-key-performance-indicators/
www.datacamp.com/community/tutorials/introduction-customer-segmentation-python
www.kaggle.com/olistbr/brazilian-ecommerce
Seja o primeiro a comentar