Profiling de CSV/TSV na linha de comando — tipos, nulos, cardinalidade, estatísticas e flags de qualidade.
dataprof lê um CSV/TSV em streaming e, por coluna, infere o tipo, conta nulos/vazios, mede a
cardinalidade, calcula estatísticas numéricas (mín/máx/média/mediana/desvio + outliers por IQR) e levanta
flags de qualidade (coluna constante, tipos misturados, espaço nas pontas, BOM, encoding suspeito).
CLI e biblioteca. Node ≥20, ESM puro, sem any.
Profilando uma amostra real de preços de combustíveis da ANP (dados abertos):
npx dataprof examples/anp-precos-glp.csv --datas-brexamples/anp-precos-glp.csv 100 linha(s), 16 coluna(s)
┌───────────────────┬────────┬────────┬───────────────┬───────┬─────┬──────────┬─────────┬─────────┬─────────────────┐
│ Coluna │ Tipo │ Nulos% │ Cardinalidade │ Mín │ Máx │ Média │ Mediana │ Desvio │ Flags │
├───────────────────┼────────┼────────┼───────────────┼───────┼─────┼──────────┼─────────┼─────────┼─────────────────┤
│ Regiao - Sigla │ string │ 0% │ 4 │ - │ - │ - │ - │ - │ - │
│ Estado - Sigla │ string │ 0% │ 11 │ - │ - │ - │ - │ - │ - │
│ Municipio │ string │ 0% │ 23 │ - │ - │ - │ - │ - │ - │
│ Revenda │ string │ 0% │ 96 │ - │ - │ - │ - │ - │ - │
│ CNPJ da Revenda │ string │ 0% │ 100 │ - │ - │ - │ - │ - │ edge-whitespace │
│ Nome da Rua │ string │ 0% │ 91 │ - │ - │ - │ - │ - │ - │
│ Numero Rua │ string │ 0% │ 94 │ - │ - │ - │ - │ - │ mixed-types │
│ Complemento │ string │ 81% │ 18 │ - │ - │ - │ - │ - │ - │
│ Bairro │ string │ 0% │ 76 │ - │ - │ - │ - │ - │ - │
│ Cep │ string │ 0% │ 83 │ - │ - │ - │ - │ - │ - │
│ Produto │ string │ 0% │ 1 │ - │ - │ - │ - │ - │ constant │
│ Data da Coleta │ date │ 0% │ 1 │ - │ - │ - │ - │ - │ constant │
│ Valor de Venda │ number │ 0% │ 31 │ 79.99 │ 130 │ 103.7963 │ 100 │ 10.9951 │ - │
│ Valor de Compra │ empty │ 100% │ 0 │ - │ - │ - │ - │ - │ - │
│ Unidade de Medida │ string │ 0% │ 1 │ - │ - │ - │ - │ - │ constant │
│ Bandeira │ string │ 0% │ 9 │ - │ - │ - │ - │ - │ - │
└───────────────────┴────────┴────────┴───────────────┴───────┴─────┴──────────┴─────────┴─────────┴─────────────────┘
Num único comando, sem configuração, o dataprof revelou:
;auto-detectado como delimitador (padrão de CSV brasileiro).Valor de Venda→numbermesmo com vírgula decimal (103,99): mín 79.99, máx 130, média ~103.80, desvio ~11.Data da Coleta→dateno formato BRDD/MM/AAAA(via--datas-br).CNPJ da Revenda→edge-whitespace: os valores vêm com espaço à esquerda.Numero Rua→mixed-types: número de rua nem sempre é número (mistura inteiros e texto).Complemento81% nulo eValor de Compra100% nulo (empty): colunas esparsas.Produto/Data da Coleta/Unidade de Medida→constant: um único valor na amostra.
--jsonemite o relatório completo (incluiq1/q3/IQRe a lista de outliers);--mdemite uma tabela Markdown.
npx dataprof arquivo.csv # sem instalar
npm i -g dataprof # ou globaldataprof <arquivo> [opções]| Flag | Descrição |
|---|---|
--json |
relatório em JSON (tudo: q1/q3/IQR, outliers) |
--md |
relatório em tabela Markdown |
--delimiter <c> |
delimitador (ex.: ;); padrão: auto-detect entre , ; e tab |
--no-header |
tratar a 1ª linha como dados |
--decimal <modo> |
marca decimal: dot | comma | auto (padrão auto) |
--datas-br |
aceitar datas DD/MM/AAAA |
--null-tokens <lista> |
tokens nulos separados por vírgula (ex.: NA,N/A,-) |
--sample <n> |
limita as linhas amostradas para estatística |
A ANP publica a série histórica em Latin-1 (ISO-8859-1). No meu projeto
dbt-dados-publicos isso precisa ser tratado na mão —
o download_anp.py tem uma função decodificar() que tenta UTF-8 e cai para latin-1, regravando como UTF-8.
Rodando o dataprof no CSV cru (Latin-1), ele aponta o mesmo problema sozinho: suspicious-encoding
nas colunas com texto acentuado (Revenda, Nome da Rua, Bairro, Bandeira):
npx dataprof examples/anp-precos-glp-latin1.csv --datas-br| Coluna | Tipo | Flags |
|---|---|---|
| Revenda | string | suspicious-encoding |
| Nome da Rua | string | suspicious-encoding |
| Bairro | string | suspicious-encoding |
| Bandeira | string | suspicious-encoding |
Em segundos, a ferramenta sinaliza o exato defeito de dado que o outro projeto teve que limpar no pipeline.
import { profile } from "dataprof";
const report = await profile("vendas.csv", { infer: { detectBrDates: true } });
for (const col of report.columns) {
console.log(col.name, col.inferredType, `${col.nullPercent}% nulos`, col.flags);
}profile(filePath, options?) devolve um ProfileReport. Tipos exportados de dataprof: ProfileReport,
ColumnProfile, NumericStats, QualityFlag, ProfileOptions, InferOptions. Também há inferType,
parseNumber e computeNumericStats para uso isolado.
Por coluna (ColumnProfile):
- inferredType:
integer|number|boolean|date|string|empty(integer + number →number). - nullCount / nullPercent / emptyCount: ausentes = vazios +
nullTokens(sentinelas comoNULL/N/A). - cardinality: nº de valores distintos (com teto configurável — reporta
100000+ao atingir o teto, não mente). - numeric (colunas numéricas):
min,max,mean,median,stddevamostral,q1,q3,iqreoutlierspelas cercas de Tukey (1,5·IQR). - flags:
constant,mixed-types,edge-whitespace,bom-detected,suspicious-encoding.
Requer Node ≥20 e pnpm.
pnpm install
pnpm dev -- examples/anp-precos-glp.csv --datas-br # roda do código (tsx)
pnpm build # bundle ESM + dts (tsup)
pnpm test # vitest + cobertura (com thresholds)
pnpm check # lint/format (Biome)
pnpm typecheck # tsc --noEmitDados de exemplo: ANP — dados abertos (Série Histórica de Preços de Combustíveis; dados comerciais de postos, sem dados pessoais).
MIT © 2026 João Matana