Análise RFM para Decisões de Negócio

Luciano Magalhães Luciano Magalhães   |   schedule Outubro, 2024  |   view_object_track Ciência de Dados


A análise RFM (Recência, Frequência e Valor Monetário) é uma ferramenta simples, mas eficaz, para segmentar clientes com base no histórico de compras. Ela é amplamente utilizada em campanhas de marketing para identificar quais clientes estão mais engajados e quais têm maior potencial de gerar receita.


Recência (R)

A recência refere-se ao tempo desde a última compra do cliente. Clientes que compraram recentemente são mais propensos a continuar interagindo com a marca. A recência pode/deve ser customizada de acordo com o segmento de negócio.

Frequência (F)

A frequência mede quantas compras foram feitas em um determinado período. Isso ajuda a identificar os clientes mais fiéis.

Valor Monetário (M)

O valor monetário no modelo RFM representa o parâmetro que gera valor para a empresa, e isso pode variar conforme o tipo de negócio.

Dessa forma, a análise RFM permite uma segmentação mais precisa dos clientes, o que facilita a criação de estratégias de marketing mais eficazes, personalizadas, e que agrega valor no negócio.

In [1]:
# suprimir avisos (warnings)  e criar função para ser aplicada nos gráficos

import warnings
warnings.filterwarnings("ignore")

Análise RFM usando Python


Carregando o Dataset e apresentando os primeiros registros do dataset

In [2]:
import pandas as pd
import numpy as np

# carregando o dataset e apresentando os primeiros registros de dados
df_transacoes = pd.read_csv('transacoes_clientes.csv')

df_transacoes.head()
Out[2]:
cliente_id data_compra valor_compra
0 cliente_82 2023-12-30 17:41:40.000000 226.84
1 cliente_290 2024-07-06 17:20:24.543626 319.40
2 cliente_99 2024-08-25 17:20:24.543626 94.12
3 cliente_88 2023-10-12 17:20:24.543626 689.68
4 cliente_67 2024-04-14 21:56:49.000000 236.31

Converção da coluna data_compra para o formato datetime e definição da data de hoje

In [3]:
from datetime import datetime  # Importando a biblioteca datetime

# Convertendo a coluna 'data_compra' para o formato datetime
df_transacoes['data_compra'] = pd.to_datetime(df_transacoes['data_compra'])

# definindo a data de hoje
hoje = datetime.today()

Calcular as três métricas do modelo RFM: recência, frequência e valor monetário.


1. Cálculo da Recência (R)

In [4]:
# calculando Recência
recencia = df_transacoes.groupby('cliente_id')['data_compra'].max().reset_index()
recencia['recencia'] = (hoje - recencia['data_compra']).dt.days

Explicação:

Aqui, o cálculo da recência é feito agrupando os dados pelo identificador do cliente (cliente_id). Para cada cliente, buscamos a data mais recente de compra usando max() na coluna data_compra. Em seguida, a métrica de recência é calculada subtraindo essa data de compra mais recente da data de referência (variável hoje, que representa o dia atual). O valor final da recência é expresso em número de dias.

Objetivo: A recência nos informa há quantos dias o cliente fez sua última compra. Quanto menor esse número, mais recente foi a interação do cliente com a empresa, sugerindo um cliente potencialmente mais engajado.


2. Cálculo da Frequência (F)

In [5]:
# calculando a Frequência
frequencia = df_transacoes.groupby('cliente_id')['cliente_id'].count().reset_index(name='frequencia')

Explicação:

Para calcular a frequência, agrupamos novamente os dados pelo identificador do cliente (cliente_id) e, em seguida, contamos o número de ocorrências de cliente_id em cada grupo. Isso nos dá a quantidade de vezes que cada cliente realizou uma compra no período de análise.

Objetivo: A frequência indica quantas vezes o cliente interagiu com o negócio ao longo do tempo. Clientes com alta frequência demonstram um nível maior de lealdade e engajamento com a empresa.


3. Cálculo do Valor Monetário (M)

In [6]:
# calculando valor monetário
valor_monetario = df_transacoes.groupby('cliente_id')['valor_compra'].sum().reset_index(name='valor_monetario')

Explicação:

A métrica de valor monetário é obtida somando o valor total das compras de cada cliente. Para isso, agrupamos os dados por cliente_id e aplicamos a função sum() na coluna valor_compra. Isso nos dá o valor total gasto por cada cliente durante o período analisado.

Objetivo: O valor monetário mede a quantidade de receita gerada por cada cliente. Clientes com um valor monetário alto representam uma parte significativa da receita da empresa e, portanto, são considerados clientes valiosos.


4. Combinação das Métricas RFM

In [7]:
# Combinando as métricas RFM em um único dataframe
df_rfm = recencia.merge(frequencia, on='cliente_id').merge(valor_monetario, on='cliente_id')

df_rfm.head()  # Exibir as primeiras linhas do dataframe
Out[7]:
cliente_id data_compra recencia frequencia valor_monetario
0 cliente_1 2024-08-01 17:20:24.545673 92 7 1854.80
1 cliente_10 2024-08-25 17:20:24.545673 68 3 883.44
2 cliente_100 2024-03-06 17:20:24.544623 240 4 996.93
3 cliente_101 2023-11-02 17:20:24.546681 365 2 507.78
4 cliente_102 2024-03-16 17:20:24.543626 230 5 1141.27

Explicação:

Após calcular individualmente as métricas de recência, frequência e valor monetário, combinamos esses três dataframes em um único dataframe chamado df_rfm. O método merge() é usado para fazer a junção dos dataframes com base no cliente_id.

Objetivo: A junção das métricas RFM em um único dataframe facilita a análise dos clientes, permitindo que as três dimensões sejam consideradas simultaneamente para tomar decisões estratégicas baseadas no comportamento do cliente.



Distribuição das Métricas RFM

Antes de realizar a segmentação, é importante visualizar como as métricas estão distribuídas entre os clientes. Isso nos ajudará a identificar padrões ou outliers que possam influenciar nossas estratégias.


Visualização da Distribuição da Recência

A distribuição da recência pode nos ajudar a identificar quantos clientes fizeram compras recentemente e quantos estão há mais tempo sem interagir com o negócio.

In [8]:
# Plotando a distribuição da recência
plt.figure(figsize=(10, 6))
sns.histplot(df_rfm['recencia'], kde=False, bins=20, color='skyblue')
plt.title('Distribuição da Recência', fontsize=16, pad=20)
plt.xlabel('Número de Dias desde a última compra', fontsize=16, labelpad=20)
plt.ylabel('Número de Clientes', fontsize=16, labelpad=20)
plt.show()
No description has been provided for this image

Explicação

Este gráfico de histograma mostra a distribuição da recência entre os clientes. Ele nos ajuda a entender quantos clientes fizeram compras recentemente em comparação com aqueles que não interagem há mais tempo. O conhecimento dessa distribuição é útil para segmentar diversos tipos de campanhas, como exemplo campanhas de reativação..



Visualização da Distribuição da Frequência

Agora, vamos analisar a frequência de compra, o que nos permite entender quantos clientes compram regularmente em comparação com aqueles que compram esporadicamente.

In [9]:
# Calculando a tabela de frequência
tabela_frequencia = df_rfm['frequencia'].value_counts().sort_index()

plt.figure(figsize=(10, 6))
tabela_frequencia.plot(kind='bar', color='lightcoral')
plt.title('Distribuição da Frequência', fontsize=16, pad=20)
plt.xlabel('Número de Compras', fontsize=16, labelpad=20)
plt.ylabel('Número de Clientes', fontsize=16, labelpad=20)

# Ajuste para que os números fiquem na orientação normal
plt.xticks(rotation=0)

plt.show()
No description has been provided for this image

Explicação

Este gráfico de frequência mostra a distribuição do número de clientes de acordo com a quantidade de compras que realizaram. Ele ajuda a visualizar quantos clientes compraram com maior ou menor regularidade, possibilitando a identificação de padrões de compra. Além disso, essa visualização pode fornecer insights sobre a lealdade do cliente, sugerindo a necessidade de campanhas de reativação para clientes com menor frequência de compras, ajudando a evitar que eles se distanciem da empresa.



Visualização da Distribuição do Valor Monetário

O valor monetário reflete quanto cada cliente gastou no total. Visualizar essa métrica nos ajuda a identificar os clientes mais valiosos.

In [10]:
# Plotando a distribuição do valor monetário
plt.figure(figsize=(10, 6))
sns.histplot(df_rfm['valor_monetario'], kde=False, bins=30, color='lightgreen')
plt.title('Distribuição do Valor Monetário', fontsize=16, pad=20)
plt.xlabel('Valor Gasto (unidades monetárias)', fontsize=16, labelpad=20)
plt.ylabel('Número de Clientes', fontsize=16, labelpad=20)
plt.show()
No description has been provided for this image

Explicação

Este gráfico nos dá uma ideia clara de como os valores de gasto estão distribuídos. Clientes que gastam mais podem ser alvo de campanhas premium, enquanto aqueles que gastam menos podem ser incentivados com ofertas especiais.


Calculando as Pontuações RFM


Após calcular as métricas individuais de Recência, Frequência e Valor Monetário, o próximo passo é atribuir pontuações a cada métrica para poder classificar os clientes. As pontuações RFM geralmente variam de 1 a 5, onde 1 indica menor prioridade e 5 maior prioridade. Neste bloco, utilizamos o método qcut para segmentar os clientes em quintis e atribuir essas pontuações de forma consistente.

In [11]:
# Calculando as Pontuações RFM ajustadas
df_rfm['pontuacao_R'] = pd.qcut(df_rfm['recencia'], 5, labels=range(5, 0, -1)).astype(int)
df_rfm['pontuacao_F'] = pd.qcut(df_rfm['frequencia'], 5, labels=range(1, 6)).astype(int)
df_rfm['pontuacao_M'] = pd.qcut(df_rfm['valor_monetario'], 5, labels=range(1, 6)).astype(int)

# Somando as pontuações para gerar a pontuação RFM final
# df_rfm['pontuacao_rfm'] = df_rfm['pontuacao_R'] + df_rfm['pontuacao_F'] + df_rfm['pontuacao_M']

# Concatenando as pontuações R, F, e M
df_rfm['pontuacao_rfm'] = df_rfm['pontuacao_R'].astype(str) + df_rfm['pontuacao_F'].astype(str) + df_rfm['pontuacao_M'].astype(str)


# Exibindo as primeiras linhas com as pontuações RFM
df_rfm.head()
Out[11]:
cliente_id data_compra recencia frequencia valor_monetario pontuacao_R pontuacao_F pontuacao_M pontuacao_rfm
0 cliente_1 2024-08-01 17:20:24.545673 92 7 1854.80 4 5 5 455
1 cliente_10 2024-08-25 17:20:24.545673 68 3 883.44 5 1 2 512
2 cliente_100 2024-03-06 17:20:24.544623 240 4 996.93 1 2 3 123
3 cliente_101 2023-11-02 17:20:24.546681 365 2 507.78 1 1 1 111
4 cliente_102 2024-03-16 17:20:24.543626 230 5 1141.27 2 3 3 233

Explicação

Foram calculadas as pontuações RFM para cada cliente com base em três métricas: Recência, Frequência e Valor Monetário. As pontuações são atribuídas de forma que clientes com melhores desempenhos nessas métricas recebam valores mais altos. A pontuação RFM total é uma combinação das três pontuações individuais (Recência, Frequência e Valor Monetário), permitindo uma visão mais abrangente do comportamento de cada cliente.



Segmentação dos Clientes com Base nas pontuações RFM

Para finalizar, vamos segmentar os clientes com base nas pontuações RFM calculadas. Abaixo, categorizamos os clientes em grupos específicos, permitindo uma análise mais direcionada.

In [12]:
# Definindo faixas de pontuação para cada categoria de clientes
def classificar_cliente(rfm):
    if rfm['pontuacao_rfm'] in ['555', '554', '545', '544', '543', '454', '455']:
        return 'Campeões'
    elif rfm['pontuacao_rfm'] in [
        '543', '444', '435', '355', '354', '345', '344', '335',
        '353', '252', '543', '541', '542', '533', '532']:
        return 'Clientes Leal'
    elif rfm['pontuacao_rfm'].startswith(('553', '551', '552', '541', '542', '533', '532')):
        return 'Potencialmente Leais'
    elif rfm['pontuacao_rfm'] in [
        '512', '511', '422', '421', '412', '411', '311']:
        return 'Novos Clientes'
    elif rfm['pontuacao_rfm'] in [
        '525', '524', '523', '522', '521', '515', '514', '513', '425', '424', '413', '414', '415']:
        return 'Promissor'
    elif rfm['pontuacao_rfm'] in [
        '535', '534', '443', '434', '343', '334', '325', '324']:
        return 'Precisa de Atenção'
    elif rfm['pontuacao_rfm'] in [
        '155', '154', '144', '214', '215', '115', '114', '113']:
        return 'Não Pode Perdê-los'
    elif rfm['pontuacao_rfm'] in [
        '331', '321', '312', '221', '213']:
        return 'Prestes a Dormir'
    elif rfm['pontuacao_rfm'] in [
        '255', '254', '245', '244', '253', '252', '243', '242', '235', '234', '225', '224', '153', 
        '152', '145', '143', '142', '135', '134', '133', '125', '124']:
        return 'Em Risco'
    elif rfm['pontuacao_rfm'] in [
        '332', '322', '231', '241', '251', '233', '232', '223', '222', '132', '123', '122', '212', '211']:
        return 'Hibernando'
    elif rfm['pontuacao_rfm'] in ['111', '112', '121', '131', '141', '151']:
        return 'Perdido'
    else:
        return 'Cliente Regular'

# Aplicando a classificação ao dataframe de pontuações RFM
df_rfm['segmento_cliente'] = df_rfm.apply(classificar_cliente, axis=1)

# Exibindo as primeiras linhas do dataframe com as classificações
df_rfm.head()
Out[12]:
cliente_id data_compra recencia frequencia valor_monetario pontuacao_R pontuacao_F pontuacao_M pontuacao_rfm segmento_cliente
0 cliente_1 2024-08-01 17:20:24.545673 92 7 1854.80 4 5 5 455 Campeões
1 cliente_10 2024-08-25 17:20:24.545673 68 3 883.44 5 1 2 512 Novos Clientes
2 cliente_100 2024-03-06 17:20:24.544623 240 4 996.93 1 2 3 123 Hibernando
3 cliente_101 2023-11-02 17:20:24.546681 365 2 507.78 1 1 1 111 Perdido
4 cliente_102 2024-03-16 17:20:24.543626 230 5 1141.27 2 3 3 233 Hibernando

Explicação

Essa segmentação nos permite categorizar os clientes com base em seus scores RFM. Por exemplo, clientes VIP têm altas pontuações em todas as três métricas, enquanto os clientes a serem recuperados têm pontuações baixas em recência e frequência. Essas informações podem ser usadas para personalizar campanhas e estratégias de marketing.



Gráfico com Comparação das Pontuações

Agora, vamos apresentar no gráfico abaixo a comparação das pontuações médias de Recência, Frequência e Valor Monetário para cada segmento de clientes, permitindo uma análise das características de cada grupo.

In [13]:
# Definindo as cores específicas para cada métrica (Recência, Frequência, Valor Monetário)
cores_metricas = {
    'pontuacao_R': '#aec6cf',  # Azul claro
    'pontuacao_F': '#ffb347',  # Laranja
    'pontuacao_M': '#77dd77'   # Verde claro
}

# Calculando a média das pontuações de Recência, Frequência e Valor Monetário para cada segmento
pontuacoes_segmentos = df_rfm.groupby('segmento_cliente')[['pontuacao_R', 'pontuacao_F', 'pontuacao_M']].mean().reset_index()

# Redefinindo o DataFrame para o formato longo (long-form) adequado para Seaborn
df_long = pd.melt(pontuacoes_segmentos, id_vars=['segmento_cliente'], value_vars=['pontuacao_R', 'pontuacao_F', 'pontuacao_M'], 
                  var_name='Métrica', value_name='Pontuação')

# Criando o gráfico de barras agrupadas
plt.figure(figsize=(12, 5))
ax = sns.barplot(x='segmento_cliente', y='Pontuação', hue='Métrica', data=df_long, 
                 palette=[cores_metricas['pontuacao_R'], cores_metricas['pontuacao_F'], cores_metricas['pontuacao_M']],
                 edgecolor='black')  # Adicionando borda preta às barras

# Ajustando os limites do eixo Y para aumentar o espaço acima da barra mais alta
max_height = max([p.get_height() for p in ax.patches])
plt.ylim(0, max_height * 1.1)  # Aumenta o limite superior para criar mais espaço

# Ajustando os títulos e rótulos dos eixos
plt.title('Comparação Média das Pontuações RFM por Segmento', pad=40, fontsize=16)
plt.xlabel('Segmentos de Clientes RFM', fontsize=14, labelpad=20)
plt.ylabel('Pontuação', fontsize=14, labelpad=20)

# Ajustando o tamanho dos textos do eixo X
plt.xticks(rotation=45, ha='right', fontsize=14)

# Posicionando a legenda horizontalmente acima do gráfico e ajustando a posição
plt.legend(title='Métricas', fontsize=12, title_fontsize=12, loc='upper center', bbox_to_anchor=(0.5, 1.10), ncol=3)

# Exibindo o gráfico
plt.show()
No description has been provided for this image


Gráfico de Comparação dos Segmentos

Agora, vamor olhar a distribuição dos clientes em diferentes segmentos RFM, como Campeões, Clientes Leais e outros, permitindo uma visão clara da quantidade de clientes em cada categoria.

In [14]:
# Contando a quantidade de clientes em cada segmento
contagem_segmentos = df_rfm['segmento_cliente'].value_counts()

# Calculando o total de clientes
total_clientes = contagem_segmentos.sum()

# Calculando os percentuais (em relação ao total de clientes)
percentuais = (contagem_segmentos / total_clientes) * 100

# Criando o gráfico com Matplotlib/Seaborn
plt.figure(figsize=(13, 6))
ax = sns.barplot(x=contagem_segmentos.index, y=contagem_segmentos.values, palette='pastel')

# Adicionando os totais e percentuais
for i, (valor, percentual) in enumerate(zip(contagem_segmentos, percentuais)):
    ax.text(i, valor - (valor * 0.2), f'{percentual:.1f}%', ha='center', va='bottom', fontsize=15, color='black')  # Percentual dentro da barra

# Ajustando os títulos e rótulos dos eixos
plt.title('Comparação dos Segmentos de Clientes RFM', fontsize=16, pad=20)
plt.xlabel('Segmentos de Clientes RFM', fontsize=16, labelpad=20)
plt.ylabel('Número de Clientes', fontsize=16, labelpad=20)

# Rotacionando os rótulos do eixo X para evitar sobreposição
plt.xticks(rotation=45, ha='right')

# Exibindo o gráfico
plt.show()
No description has been provided for this image

Explicação

Esse gráfico pode nos auxiliar na identificação de quais segmentos possuem maior quantidade de clientes, oferecendo insights para estratégias de marketing específicas.



Gráfico de Dispersão (Scatter Plot)

Vamos agora apresentar gráficos de dispersão que mostram a relação entre duas variáveis, como recência e valor monetário ou frequência e valor monetário. Eles irão ajudar a identificar correlações e padrões que não são visíveis apenas nas distribuições individuais.

In [15]:
# Gráficos de dispersão para as métricas RFM
plt.figure(figsize=(15, 5))

# Dispersão de Recência vs Valor Monetário
plt.subplot(1, 2, 1)
sns.scatterplot(x='recencia', y='valor_monetario', data=df_rfm, palette='pastel')
plt.title('Recência vs Valor Monetário', fontsize=16, pad=20)
plt.xlabel('Recência (dias)', fontsize=16, labelpad=20)
plt.ylabel('Valor Monetário (total)', fontsize=16, labelpad=20)

# Dispersão de Frequência vs Valor Monetário
plt.subplot(1, 2, 2)
sns.scatterplot(x='frequencia', y='valor_monetario', data=df_rfm, palette='pastel')
plt.title('Frequência vs Valor Monetário', fontsize=16, pad=20)
plt.xlabel('Frequência (compras)', fontsize=16, labelpad=20)
plt.ylabel('Valor Monetário (total)', fontsize=16, labelpad=20)

plt.tight_layout()
plt.show()
No description has been provided for this image

Explicação

Nesses gráficos de dispersão comparamos a recência e a frequência de compras em relação ao valor monetário total, proporcionando uma visão clara das interações entre essas variáveis. No primeiro gráfico notamos como clientes com recência menor tendem a gerar maiores valores monetários. Isso pode indicar que clientes que compraram recentemente ainda estão engajados e gerando mais receita. No segundo gráfico, observamos uma correlação positiva, ou seja, conforme a frequência de compras aumenta, o valor monetário total também tende a crescer, sugerindo que clientes recorrentes geralmente gastam mais.

Esses gráficos ajudam a identificar padrões que podem direcionar estratégias, como focar em clientes com alta frequência para programas de fidelização ou monitorar aqueles com baixa recência, mas alto valor, para reativação.



Gráficos de Calor (Heatmaps)

Em seguida, vamos analisar a correlação entre as três métricas principais do modelo RFM utilizando um gráfico de calor (heatmap).

In [16]:
# Gráfico de Calor (Heatmap) para as correlações entre as métricas RFM
plt.figure(figsize=(10, 6))
correlacao = df_rfm[['recencia', 'frequencia', 'valor_monetario']].corr()

# Plotando o heatmap
sns.heatmap(correlacao, annot=True, cmap='coolwarm', vmin=-1, vmax=1)
plt.title('Correlação entre Métricas RFM', fontsize=16, pad=20)

plt.show()
No description has been provided for this image

Explicação

O heatmap nos mostra uma correlação positiva forte entre Frequência e Valor Monetário, sugerindo que clientes que compram com mais frequência tendem a gastar mais. Esse insight é valioso para estratégias que buscam aumentar o valor de cada cliente por meio de compras mais frequentes.



Conclusão

A análise RFM é uma estratégia eficaz para segmentar clientes, utilizando três métricas principais: recência, frequência e valor monetário. Essa abordagem ajuda categorizar os clientes com base em seu comportamento, ajustar as estratégias da empresa para melhorar o relacionamento com eles, e gerar valor no negócio. Além disso, os gráficos dessas métricas fornecem insights visuais importantes sobre a interação dos clientes com o negócio.

Espero que tenham gostado deste artigo sobre Análise RFM usando Python.


© Copyright 2024 | Luciano Magalhães