Como realizar a seleção de amostras para inspeção de forma efetiva.
O objetivo desse artigo é explicar como realizar a seleção de amostras em processos de auditoria para identificação de fraudes usando a Lei de Benford em Python.
Essa é uma lei curiosa: ela é uma observação de que em muitos conjuntos de dados numéricos, o dígito inicial provavelmente será pequeno (e.g. 1, 2…). Em séries de registros que obedecem à lei, o número 1 aparecerá como o primeiro dígito significativo em cerca de 30% das vezes, enquanto 9 aparece como o primeiro dígito significativo em menos de 5% das vezes.
Sua aplicação se dá em diversos campos, sendo o mais comum na área de identificação de red flags sobre transações financeiras. Entretanto, seu uso possui limitações, ainda que seja legamente aceita como evidência em casos criminais nas esferas locais, estaduais e federais dos EUA, de acodo com a Information Systems Audit and Control Association (ISACA).
A Lei de Benford é utilizada para a identificação de anomalias em séries de dados, não sendo bala de prata para a identificação de fraudes, ainda que seu uso seja de grande valia e um direcionador.
Neste caso em questão, utilizarei a biblioteca benford_py
do Python para a identificação de possíveis fraudes no dataset Credit
Card Fraud Detection. Esse dataset trás transações realizadas por
clientes europeus no ano de 2013, tendo ao todo 284.807 registros, sendo
fraudes 492 desses dados. A ideia aqui é simular uma possível seleção de
transações para inspeção mais rigorosa, dada o tamanho elevado da base
da dados. Assim, o objetivo é realizar a avaliação da base de dados
usando a Lei de Benford e então definir a seleção de amostras de
determinados grupos de números, caso sejam observadas anomalias.
Inicialmente será feito o carregamento da base e a seleção de registros:
import benford as bf
import pandas as pd
fraud_df = (pd.read_csv("creditcard.csv")
.query('Amount >= 1')
.assign(Amount_Str=lambda x: x.Amount.astype(str).str.replace('.', '', regex=True))
)Além de serem filtradas apenas transações com Montantes acima de €
1,00, também foi adicionada uma coluna com os valores dos Montantes em
formato string para facilitar a manipulação dos dados. O filtro
dos valores foi pelo fato de que a Lei se dá apenas para valores entre
1-9. Em seguida, foi aplicado o método bf.first_digits
usando a coluna Amount do dataset para se obter o
comportamento dos dados das movimentações. Nesse caso, foram agrupados
os registros a partir dos 2 primeiros dígitos dos Montantes:
bf.first_digits(fraud_df.Amount, digs=2)O resultado pode ser observado na imagem abaixo:
Nesse caso, o direcionamento para seleção das amostras será feito de forma visual, entretanto para uma avaliação mais criteriosa pode-se optar por um teste estatístico, como o de Kolmogorov-Smirnov por exemplo. Nesse caso, foi possível observar que os montantes que se iniciam com 10, 19, 89 e 99 fogem de forma drástica da distribuição teórica dos dados, indicando possíveis anomalias com esses valores. A partir dessa informação, pode proceder com uma análise mais direcionada para a obtenção das amostras.
Para aquisição dos registros a serem amostrados, a base de dados será filtrada usando os valores indicados na análise visual do gráfico de distribuição:
(fraud_df
.query("Amount_Str.str.startswith(tuple(['99', '89', '19', '10']))")
)A base de dados então foi reduzida a 48.991 linhas. Ainda é uma base grande (268.003 - lembre-se que foi feito um filtro dos valores abaixo de € 1,00 no dataset), porém de tamanho menor que a inicial. A partir daqui podem ser usadas outras técnicas e inteligências direcionadoras para uma melhor definição do grupo a ser amostrado, como selecionar os valores de Montantes que mais se repetem na série.
A essa altura você deve estar pensando:
sim, mas quem me garante que essa técnica é efetiva?
Como o dataset, diferente da vida real, possui uma coluna
Class indicando fraudes (1) e não-fraudes (2), podemos
investigar o quanto os valores identificados (‘99’, ‘89’, ‘19’, ‘10’)
correspondem a fraudes na base completa:
(fraud_df
.query("Amount_Str.str.startswith(tuple(['99', '89', '19', '10'])) and \
Class == 1")
)No total, os valores iniciados em 10, 19, 89 e 99 correspodem a 166 registros da base de dados. Esse valor corresponde à aproximadamente 40% de todas as fraudes identificadas (424 após filtragem inicial). Esse resultado indica que a utilização da Lei de Benford para identificar possíveis fraudes em uma base de dados é uma estratégica efetiva e que pode otimizar o trabalho de auditoria, tornando a definiçao de amostras mais dinâmica.
Até a próxima!