Pular para o conteúdo

Qualidade de dados

As seis dimensões, medidas e cobradas como parte do pipeline — não como um assert no fim.

Qualidade não é uma etapa no fim: é parte do pipeline. Arcane.Qualidade cobre as seis dimensões clássicas — completude, validade, unicidade, consistência, precisão e atualidade.

Por que isto não é um `assert`#

dataforge
assert todas(linhas, lambda l: l["id"] is not void)

Isso responde passou? e nada mais. Quando falha — e vai falhar, com dado de verdade — não diz qual linha, quantas, nem se é um caso isolado ou metade do arquivo. E é essa diferença que decide se o pipeline para ou segue.

text
✗ 40000 linha(s), 3 violação(ões), 99.9% boas

  email  —  3 (0.0%)
      linha 1204: 'ana@' — fora do formato email
      linha 8891: 'sem-arroba' — fora do formato email
      linha 30112: '@dominio.co' — fora do formato email

3 de 40.000 com e-mail inválido leva a uma decisão. falhou leva a abrir o arquivo no editor.

Regras#

dataforge
REGRAS := {
    "id":       {"obrigatorio": yes, "tipo": "inteiro", "unico": yes},
    "produto":  {"obrigatorio": yes, "tipo": "texto", "minimo": 2, "maximo": 80},
    "valor":    {"tipo": "numero", "minimo": 0},
    "email":    {"formato": "email"},
    "situacao": {"em": ["ativo", "inativo"]},
    "score":    {"confere": lambda v: v % 2 is 0},
}

r := Q.conferir(linhas, REGRAS)
RegraCobra
obrigatorioveio preenchido — void, "" e " " contam como vazio
tipointeiro, numero, texto, booleano, lista, vault
formatoemail, url, uuid, data, data_hora, cpf, cnpj, cep, telefone — ou o seu regex
minimo / maximoo valor, se for número; o tamanho, se for texto ou lista
emestá na lista permitida
unicoa chave não se repete
conferea sua própria regra, como ação

Dentro do pipeline#

dataforge
action conferir(ctx):
    // levanta se a taxa boa ficar abaixo de 99%
    yield Q.esperar(ctx["limpar"], REGRAS, 0.99)

O mínimo existe porque nem todo dado precisa ser perfeito. Um arquivo com 0,1% de e-mails inválidos costuma poder seguir, e parar por isso seria pior que o problema. Quando ele levanta, a mensagem traz a taxa, quantas linhas e os cinco campos que mais falharam.

Perfil — quando o arquivo é desconhecido#

Mede sem regra nenhuma. É por onde se começa, e é a partir daí que se escreve a regra:

dataforge
p := Q.perfil(linhas)

// por campo:
//   preenchidos, vazios, completude
//   distintos, tipos, tipo_misto
//   minimo, maximo, media, mediana   (quando numérico)
//   menor_texto, maior_texto          (quando texto)
//   parece_chave                      (quando todos distintos)

Limpar#

dataforge
Q.sem_duplicadas(linhas, ["id"])     // mantém a PRIMEIRA de cada chave
Q.so_validas(linhas, REGRAS)         // só o que passa em tudo
Q.preencher(linhas, {"situacao": "ativo"})   // só o que está vazio

sem_duplicadas mantém a primeira, e não a última: em dado de origem a ordem costuma ser a de chegada, e a primeira é a original. É a mesma regra que faz conferir marcar o repetido na segunda ocorrência.

As dimensões, isoladas#

dataforge
Q.completude(linhas)                   // proporção preenchida por campo
Q.unicidade(linhas, "id")              // 1.0 = é chave
Q.duplicadas(linhas, ["id"])           // as repetidas, agrupadas
Q.fora_da_faixa(linhas, "valor", 0, 1000)
Q.atualidade(linhas, "atualizado_em", 7)   // quantas passaram de 7 dias

Atualidade é a dimensão que mais escapa da validação. Dado antigo não é dado errado — é dado que passou a mentir sem avisar.