Skip to main content

dq-engine

Framework PySpark para validacao e tratamento de qualidade de dados.

O que faz

  • Resolve rule_set por nome de coluna
  • Compila regras declarativas em expressoes Spark
  • Gera score e status por coluna
  • Aplica tratamento em lote (inclui colapso de espacos internos em texto DSC_)
  • Executa pipeline antes/depois com comparativo
  • Detecta avisos (informativos, nao alteram o score):
    • cardinalidade IDT_ fora do padrao;
    • similaridade categorica DSC_/TPO_ — mesma categoria com grafia diferente, por pontuacao/espacos (ex.: "S.A" vs "S/A");
    • nulos padronizados (N/D/0/1800-01-01) por coluna, marcando [DROP?] quando sao maioria.
  • Registra em dq_historico.xlsx (abas Historico com % Colunas Aprovadas, Relatorio com Causa/Acao Sugerida, e Avisos)
  • Suporta modo producao (valida o DataFrame ja tratado e marca situacao CORRIGIDO)

Requisitos

  • Python 3.10+
  • PySpark 3.4+

Instalacao

pip install -e .

Uso rapido

from pyspark.sql import SparkSession
from dq_engine import DataQualityEngine
from dq_engine.config.conventions import CONVENTIONS

spark = SparkSession.builder.getOrCreate()
engine = DataQualityEngine(spark=spark, conventions=CONVENTIONS)

df = spark.table("lakehouse.clientes")
result = engine.validate_table(df=df, table_name="CLIENTES", run_id="2026-07-02")

result.output_df.orderBy("column_name").show(truncate=False)

Dois modos de uso

Modo Quando usar O que faz
Simulacao (padrao) Antes de levar o tratamento para o ETL Valida o dado bruto, aplica o tratamento, valida de novo e compara ANTES x DEPOIS. Imprime o trecho de ETL (treat_*) para copiar e colar.
Producao (producao=True) Depois que o ETL real ja aplicou o data clean Valida uma unica vez o dado ja tratado (nao re-trata) e marca a situacao como CORRIGIDO, ou PENDENTE_FONTE se sobrar falha.

Simulacao

df_tratado, result_before, result_after = engine.run_dq_pipeline(
    df=df,
    table_name="CLIENTES",
    output_dir="/mnt/dq_output",  # opcional: sem ele nada e gravado em arquivo
)

Producao

df_validado, result, _ = engine.run_dq_pipeline(
    df=df_ja_tratado,
    table_name="CLIENTES",
    output_dir="/mnt/dq_output",
    producao=True,
    ignore_columns_from_score=[],   # lista de colunas a tirar do score (veja abaixo)
)

Ignorar colunas no score (ignore_columns_from_score)

Para uma particularidade ja conhecida e nao corrigivel agora (ex.: IDT_X que na verdade deveria ser TPO_X), informe o nome exato da coluna:

df_validado, result, _ = engine.run_dq_pipeline(
    df=df_ja_tratado,
    table_name="CLIENTES",
    output_dir="/mnt/dq_output",
    producao=True,
    ignore_columns_from_score=["IDT_SITUACAO", "IDT_SUBCATEGORIA"],
)
  • So tem efeito com producao=True (em simulacao e ignorado).
  • A coluna continua sendo validada; apenas fica fora do quality_score/indicador da tabela e do diagnostico de falha residual. Nao e manipular score, e priorizar.
  • O estado real da coluna e mostrado no console/.txt (subsecao "COLUNAS MONITORADAS") e gravado na aba Avisos do Excel (Tipo Aviso = COLUNA_MONITORADA) para ajuste posterior.
  • [] (ou omitir) = todas as colunas entram no score.

Via main.py: python main.py --table ... --producao --ignore-columns-producao IDT_X (flag repetivel), ou no .env: DQ_PRODUCAO=true e DQ_IGNORE_COLUMNS_PRODUCAO=IDT_X,IDT_Y.

Como ler o output

O output tem dois blocos de aviso:

  1. PONTO DE ATENCAO — nao reduz o score. Um bloco unico, em subsecoes:
    • IDT_ fora do padrao de dominio (mais de 2 valores distintos alem de N/D: provavel erro de prefixo, deveria ser TPO_/DSC_);
    • regras WARNING (ex.: ano suspeito em datas, campos estritos como CPF/CNPJ/placa/chassi), sempre com exemplos dos valores que dispararam a regra. Colunas DSC_ (campo aberto) nao validam encoding_corruption;
    • categorias duplicadas por grafia (S.A x S/A);
    • colunas monitoradas (fora do score).
  2. FALHA RESIDUAL — reduz o score. Colunas que seguem com falha. Cada regra aparece separada, com o que significa, quantas linhas, exemplos daquela regra e a acao:
    • "o tratamento corrige" (nulo fora do padrao, placeholder, maiusculas...): se aparece em producao, a tabela nao foi reprocessada com o data_clean atual;
    • "o tratamento NAO corrige" (texto so com numero, encoding, dominio, formato): corrigir na fonte ou rever o prefixo da coluna.

Tudo isso vai tambem para o Excel (aba Avisos), com coluna, regra, categoria, quantidade e mensagem (incluindo exemplos).

Regras de tratamento de texto

Todo tratamento de string converte para MAIUSCULAS, remove acentos e trata nulos (N/D), exceto:

  • COD_ — mantem o texto como veio (so trim): sem upper, preserva pontuacao, acentos e minusculas — codigos/chaves nao mudam. O nulo de COD_ e sempre "0" (nunca N/D), inclusive em COD_ com regra propria pelo nome (COD_CHASSI, COD_UF, COD_CPF...), que mantem a validacao/avisos do campo mas devolvem "0" no nulo;
  • colunas com PATH ou LINK no nome (qualquer prefixo) e DSC_ com BUCKET/CAMINHO (treat_dsc_path) — nao passam para maiusculas: preservam o caminho/link e usam minusculas.

Datas (DAT_/DTH_) sao sempre timestamp (padrao das tabelas trusted TRU_): treat_date e treat_datetime devolvem TimestampType, preservam a hora e, para data sem hora, usam 00:00:00. Nulo/invalido vira 1800-01-01 00:00:00, assim como datas com ano abaixo de suspicious_year_min (default 1900, ex.: 0001-01-01). Datas futuras sao mantidas e so geram aviso (ano suspeito). Tabelas REP_/REF_ (colunas date) nao tem tratamento especifico no dq-engine.

DSC_ (texto livre ou categorica, de baixa cardinalidade) e STR_ usam a mesma funcao, treat_dsc. DSC_ capturadas por nome (ex.: DSC_PLACA) mantem o tratamento especifico mesmo com baixa cardinalidade.

  • Simbolos em qualquer posicao: treat_dsc mantem letras, numeros, espaco e a pontuacao . , ; : - / ( ) [ ] ' " ? ! % & + = @ _; o resto (* # | ~ ^ $ < >, emojis...) e removido tambem no meio do texto ("EVENTO** RELATO" -> EVENTO RELATO).
  • Ruido nas bordas: simbolos soltos no inicio/fim saem ("SUZANO *" -> SUZANO, "UBERABA." -> UBERABA), mas (/[ no inicio e )/]/% no fim ficam ("... (GASOLINA / FLEX)" mantem o ) final).
  • Placeholders: X, TESTE e sequencia de zeros (0, 000000) viram N/D.

Funcoes treat_* do trecho de ETL sao sempre as mesmas desde a 0.7.2 — ajustes novos mudam o comportamento dessas funcoes, sem criar nomes novos. Para os ajustes valerem nos ETLs que ja estao em producao (que chamam a funcao gravada no trecho da epoca), cada treat_* aplica a regra da familia pelo nome da coluna:

Chamada no ETL Coluna Regra aplicada
treat_string / treat_dsc / treat_dsc_path COD_* (ex.: COD_APOLICE, COD_DOCUMENTO, COD_LINK) treat_cod (texto mantido, nulo "0")
treat_string / treat_dsc nome com PATH/LINK treat_dsc_path
treat_string DSC_* / STR_* treat_dsc
treat_float NUM_* / QTD_* treat_int

COD_ com campo estrito (COD_CHASSI, COD_UF, COD_CPF...) continua com a validacao do campo, mas o nulo e "0".

Tipos numericos

Prefixo Tipo Tratamento
VAL_, PERC_ float treat_float (treat_string em VAL_/PERC_ tambem vira float)
NUM_, QTD_ int treat_int (decimais sao truncados; coluna com casas decimais deve ser VAL_)

Excecoes pelo nome continuam com a regra propria: NUM_APOLICE/NUM_DOCUMENTO (texto), NUM_TELEFONE, NUM_CHASSI, NUM_CPF.../NUM_CNPJ.... Atencao: int vai ate 2.147.483.647 — colunas NUM_ com mais digitos (protocolos, notas fiscais) estouram.

Campos estritos: so aviso, valor invalido mantido

CPF, CNPJ, CEP, UF, telefone, placa e chassi (resolvidos pelo nome da coluna) nao afetam o score — todas as regras sao WARNING e aparecem na aba Avisos. No tratamento:

  • nulo disfarcado (VAZIO, 0, TESTE, 000.000.000-00, vazio) -> N/D;
  • valor valido -> forma padronizada (sem mascara; telefone como (XX) XXXXX-XXXX);
  • valor invalido -> mantido como veio, com aviso "valor mantido; corrigir na origem" (ex.: CNPJ incompleto continua incompleto).

Avisos especificos, alem de formato/nulo:

Aviso Quando
cpf_check_digit / cnpj_check_digit digito verificador invalido ou digitos repetidos
chassi_check_digit chassi com formato valido mas digito verificador (ISO 3779) divergente
telefone_ddd DDD inexistente na Anatel
placa_padrao_antigo placa ABC1234 — nao e convertida para Mercosul
domain (UF) nome por extenso ou codigo IBGE — nao e convertido para sigla

No modo simulacao, problemas que o tratamento corrigiu (ex.: nulo disfarcado -> N/D) tambem continuam na aba Avisos, com a indicacao "trocado(s) por N/D no tratamento".

Onde os arquivos sao salvos

Quando output_dir e informado, o DqOutputSaver grava:

{output_dir}/
├── table_output/
│   └── {TABELA}_{TIMESTAMP}.txt        # relatorio detalhado de cada execucao
└── output_consolidado/
    └── dq_historico_v2.xlsx            # historico acumulado (nome via historico_filename)

Abas do Excel: Historico (indicador/score por execucao), Relatorio (diagnostico por coluna), Avisos (todos os avisos acima) e Distribuicao (opcional, include_distribution=True).

No main.py a configuracao e:

Item Flag / .env Default
Pasta de saida --output-dir / DQ_OUTPUT_DIR \KIRIBATI.autoglass.com.br\Departamento$\Célula de Dados e Implantação\Engenharia\Outputs_Data_Quality
Nome do Excel --historico-filename / DQ_HISTORICO_FILENAME dq_historico_v2.xlsx
Tabelas ja processadas --processed-file / DQ_PROCESSED_FILE state/processed_tables.yaml
Tabelas com falha --failed-file / DQ_FAILED_FILE state/failed_tables.yaml

Se o Excel estiver aberto, o save avisa e nao grava o registro: feche e rode de novo.

Leitura via Snowflake (opcional)

O engine sempre recebe um DataFrame Spark comum — a origem dos dados e desacoplada. Para descobrir e ler tabelas do Snowflake por schema, instale o extra snowflake:

pip install -e ".[snowflake]"
from dq_engine.sources.snowflake_source import SnowflakeReader, discover_tables

reader = SnowflakeReader()  # credenciais via variaveis de ambiente (.env)
table_names = discover_tables(reader, schema_like="%NOME_DO_SCHEMA%")
df = reader.read(spark, table_names[0])

result = engine.validate_table(df=df, table_name=table_names[0], run_id="2026-07-14")

O script main.py automatiza o fluxo (descobre tabelas do schema -> roda dq-engine -> salva consolidado/historico) e pode ser agendado no Sonata:

python main.py --schema-like "%NOME_DO_SCHEMA%"

O padrao LIKE tambem pode vir do .env (variavel TABLE_SCHEMA), dispensando --schema-like em toda chamada.

Tambem e possivel rodar uma lista fixa de tabelas em vez de (ou combinada com) o schema, via --table (repetivel) ou pela variavel TABLE_LIST no .env (nomes completos DATABASE.SCHEMA.TABELA separados por virgula):

python main.py --table TRUSTED.MAX_APOLICE.TABELA_1 --table TRUSTED.MAX_APOLICE.TABELA_2

Tambem e possivel apontar um YAML com lista simples de tabelas (como to_process.yaml) usando --tables-yaml ou a variavel TABLE_LIST_FILE no .env:

python main.py --tables-yaml to_process.yaml

Sem --schema-like/TABLE_SCHEMA, o main.py roda so as tabelas informadas (--table, TABLE_LIST ou --tables-yaml), sem descoberta via INFORMATION_SCHEMA; com os dois informados, a lista filtra o resultado da descoberta.

Tabelas processadas com sucesso ficam registradas em processed_tables.yaml (arquivo temporario, desacoplado do dq-engine) e sao puladas nas proximas execucoes; use --rerun-processed para forcar tudo de novo.

API principal

  • DataQualityEngine.validate_table
  • DataQualityEngine.apply_treatment
  • DataQualityEngine.run_dq_pipeline
  • DataQualityEngine.get_column_treatment_contexts
  • DataQualityResult.table_summary
  • DataQualityResult.failed_columns

Configuracao

Arquivo central de convencoes:

  • src/dq_engine/config/conventions.py

Documentacao

  • docs/architecture.md
  • docs/rules.md

Metadata

Release files for dq-engine 0.7.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dq-engine 0.7.5
File Size Uploaded
dq_engine-0.7.5.tar.gz 85.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for dq-engine 0.7.5
File Interpreter ABI Platform
dq_engine-0.7.5-py3-none-any.whl Python 3 none any Details

Total release size: 173.3 kB

Release files / dq_engine-0.7.5.tar.gz

Download URL dq_engine-0.7.5.tar.gz
Size 85.9 kB
Tags Source
SHA-256 checksum
How to use checksums
4b0168d5a556a6af955f2635bc395bb4ef04184ee6a085bc6391a15ca4ede892
BLAKE2b-256 checksum
How to use checksums
8115e90bad54fe81733f7227dc92f45cb47e40642b4e988ab4f0a524b1af4088
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.0

Release files / dq_engine-0.7.5-py3-none-any.whl

Download URL dq_engine-0.7.5-py3-none-any.whl
Size 87.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c0a867ce27128cdf477446a2cebd26ad8bf792129cde9fdb8f08da0fa321539a
BLAKE2b-256 checksum
How to use checksums
c99114f60a6369311bdf6add184533dd6536183e477e639a7ba07c364bfb786c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.0

Release history Release notifications | RSS feed

This release

0.7.5 This release

2 release files

0.7.4

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.5

2 release files

0.5.4

2 release files

0.5.3

2 release files

0.5.0

2 release files

0.4.7

2 release files

0.4.6

2 release files

0.4.5

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.3.14

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page