Olá pessoal,
Nessa etapa do projeto, tive a oportunidade de comparar minha abordagem com a do instrutor — e acabei encontrando uma divergência importante que me fez seguir um caminho diferente.
Ponto inicial semelhante
Assim como o instrutor, comecei analisando os registros com valores vazios ou inconsistentes na coluna 'conta.cobranca.Total'
:
dados_normalizados[dados_normalizados['conta.cobranca.Total'] == ' '].head()
Mas algo chamou minha atenção...
Ao investigar melhor os dados, percebi uma incoerência: nem todos os clientes com contrato de "dois anos" tinham exatamente 24 meses registrados em cliente.tempo_servico
.
Então executei essa linha:
dados_normalizados.loc[
dados_normalizados['conta.contrato'] == 'dois anos',
'cliente.tempo_servico'
].value_counts(dropna=False)
E o resultado foi esse:
72.0 353
71.0 142
...
1.0 2
28.0 1
Name: count, Length: 74, dtype: int64
Isso mostrou que:
- Há 74 valores distintos de
cliente.tempo_servico
associados ao contrato de "dois anos" - O valor mais comum foi 72 meses (6 anos), não 24
- Outros registros variavam desde 1 até 71 meses
Conclusão da análise
Identifiquei que:
- A informação
"dois anos"
na colunaconta.contrato
nem sempre corresponde a 24 meses no campocliente.tempo_servico
. - Na verdade, muitas vezes ela representa contratos bem mais antigos (como 6 anos).
- Isso indica que o campo
cliente.tempo_servico
representa o tempo real de uso do serviço, enquantoconta.contrato
parece ser apenas o tipo de plano contratado.
Portanto, atribuir 24 meses automaticamente seria incorreto nesse caso.
Minha abordagem alternativa
Com base nessa descoberta, optei por seguir um caminho mais seguro e fundamentado nos próprios dados:
- Preenchi valores ausentes em colunas numéricas com zero
dados_normalizados = dados_normalizados.fillna({
'cliente.tempo_servico': 0,
'conta.cobranca.mensal': 0
})
- Criei uma máscara para identificar valores inválidos em
conta.cobranca.Total
cols = ['cliente.tempo_servico', 'conta.contrato', 'conta.cobranca.mensal', 'conta.cobranca.Total']
pattern = r'^\d+(\.\d+)?$' # Aceita números inteiros ou decimais
mask = (
dados_normalizados['conta.cobranca.Total'].isna() |
~dados_normalizados['conta.cobranca.Total'].str.match(pattern, na=False)
)
- Atualizei os valores com base no cálculo real entre tempo de serviço e mensalidade
idx = dados_normalizados.loc[mask, cols].index
dados_normalizados.loc[idx, 'conta.cobranca.Total'] = (
dados_normalizados.loc[idx, 'cliente.tempo_servico'] *
dados_normalizados.loc[idx, 'conta.cobranca.mensal']
)
- Converti a coluna para
float
no final
dados_normalizados['conta.cobranca.Total'] = dados_normalizados['conta.cobranca.Total'].astype(float)
Resultado final
Após a transformação, a coluna 'conta.cobranca.Total'
ficou consistente e alinhada com os dados reais do cliente:
dados_normalizados.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 7344 entries, 0 to 7343
Data columns (total 21 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
...
6 cliente.tempo_servico 7344 non-null float64
...
19 conta.cobranca.mensal 7344 non-null float64
20 conta.cobranca.Total 7344 non-null float64
dtypes: float64(3), int64(1), object(17)
memory usage: 1.2+ MB
Amostra de linhas alteradas:
dados_normalizados.loc[idx, cols]
conta.contrato | cliente.tempo_servico | conta.cobranca.mensal | conta.cobranca.Total |
---|---|---|---|
None | 9.0 | 0.00 | 0.0 |
None | 18.0 | 20.05 | 360.9 |
dois anos | 0.0 | 80.85 | 0.0 |
dois anos | 60.0 | 20.95 | 1257.0 |
Considerações finais
Essa experiência reforçou a importância de explorar os dados antes de aplicar transformações fixas. Às vezes, a lógica aparentemente mais simples pode esconder nuances importantes — como a diferença entre tempo contratado e tempo efetivo de serviço.
Abraço!