Crie um dicionário de dados com significados, unidades, tipos e valores permitidos
Documente o significado de cada coluna do conjunto de dados antes da análise, incluindo unidade, tipo de dado e valores permitidos. Um pequeno conjunto de dados sintético mostra como o mesmo dicionário também pode servir para uma validação automática simples.
Conteúdo verificado 2026.09.20Inclui arquivos de exemplo
Ver o sumário
A tradução foi feita com IA. Confira o código, as unidades e os valores junto com o original. A revisão por falantes nativos de cada idioma ainda não foi concluída. English
Para quem éEste guia é voltado a pesquisadores que precisam de uma descrição clara, coluna por coluna, de um conjunto de dados que outras pessoas possam ler e verificar.
Preparação
Python 3.12 e um comando de terminal que inicie essa versão.
Um editor de texto ou programa de planilhas capaz de salvar arquivos CSV em UTF-8.
Uma pasta de trabalho em que o script possa criar uma nova pasta dentro de outputs.
É necessária apenas a biblioteca padrão do Python: csv, pathlib e re.
01Trate o dicionário de dados como parte do conjunto de dados
O nome de uma coluna raramente é suficiente para descrever dados de pesquisa. speed pode significar velocidade do veículo, velocidade da roda ou velocidade angular. accel pode significar aceleração longitudinal, lateral ou total. Um dicionário de dados registra o significado pretendido para que análises posteriores não dependam de suposições.
Este tutorial registra seis informações para cada coluna: nome da coluna, significado, unidade, tipo de dado, valores permitidos e um exemplo. O campo de valores permitidos pode descrever categorias, intervalos numéricos, regras de unicidade ou padrões simples de texto.
02Crie um pequeno conjunto de dados sintético de pesquisa
O conjunto de dados a seguir é sintético e foi criado especificamente para este artigo. Salve-o como test_runs.csv. Quatro linhas seguem as regras pretendidas. A quinta linha contém deliberadamente quatro problemas para que o dicionário possa ser usado como referência de validação.
Há 5 linhas e 5 colunas. R005 tem um speed acima do intervalo permitido, um valor de acceleration não numérico, uma categoria de road-surface não suportada e um valor de test-status não suportado. O próprio run_id é válido.
03Escreva manualmente o dicionário de dados esperado
O dicionário deve ser compreensível sem abrir o código de análise. Mantenha o significado específico o suficiente para que outro pesquisador consiga distinguir a coluna de medições semelhantes.
column_name
significado
unidade
tipo
valores permitidos
exemplo
run_id
Identificador exclusivo de uma execução de teste
string
R seguido de exatamente 3 dígitos; exclusivo
R001
speed_kmh
Velocidade do veículo no início do registro
km/h
inteiro
0 a 120 inclusive
50
accel_m_s2
Aceleração longitudinal
m/s^2
ponto flutuante
-5.0 a 5.0 inclusive
-1.2
road_surface
Condição da superfície da via usada no teste
categoria
dry;wet
wet
test_status
Estado de revisão do registro de teste
categoria
complete;review
complete
Uma unidade vazia é intencional para identificadores e rótulos categóricos porque eles são metadados adimensionais, e não grandezas físicas medidas. O campo type descreve a representação de dados pretendida, e não o que uma planilha por acaso infere automaticamente.
04Gere o dicionário e valide o conjunto de dados
Salve o script a seguir como data_dictionary_check.py. A especificação das colunas é escrita uma única vez em SPEC. O script exporta essa especificação como data_dictionary.csv e verifica cada linha usando as mesmas regras. O arquivo original test_runs.csv é apenas lido.
python
import csv
import re
from pathlib import Path
SOURCE = Path("test_runs.csv")
OUTPUT_DIR = Path("outputs") / "data_dictionary_result"
DICTIONARY = OUTPUT_DIR / "data_dictionary.csv"
ISSUES = OUTPUT_DIR / "validation_issues.csv"
SPEC = [
{
"column_name": "run_id",
"meaning": "Unique identifier for one test run",
"unit": "",
"type": "string",
"allowed_values": "R followed by exactly 3 digits; unique",
"example": "R001",
},
{
"column_name": "speed_kmh",
"meaning": "Vehicle speed at the start of the record",
"unit": "km/h",
"type": "integer",
"allowed_values": "0 to 120 inclusive",
"example": "50",
},
{
"column_name": "accel_m_s2",
"meaning": "Longitudinal acceleration",
"unit": "m/s^2",
"type": "float",
"allowed_values": "-5.0 to 5.0 inclusive",
"example": "-1.2",
},
{
"column_name": "road_surface",
"meaning": "Road-surface condition used for the test",
"unit": "",
"type": "category",
"allowed_values": "dry;wet",
"example": "wet",
},
{
"column_name": "test_status",
"meaning": "Review state of the test record",
"unit": "",
"type": "category",
"allowed_values": "complete;review",
"example": "complete",
},
]
def issue(row_number, column, value, problem):
return {
"row_number": row_number,
"column_name": column,
"value": value,
"issue": problem,
}
def main() -> None:
if not SOURCE.is_file():
raise FileNotFoundError(f"Source CSV not found: {SOURCE}")
if OUTPUT_DIR.exists():
raise FileExistsError(f"Output folder already exists: {OUTPUT_DIR}")
expected_columns = [item["column_name"] for item in SPEC]
issues = []
seen_run_ids = set()
row_count = 0
with SOURCE.open("r", encoding="utf-8-sig", newline="") as stream:
reader = csv.DictReader(stream)
if reader.fieldnames != expected_columns:
raise ValueError(
f"Header mismatch. Expected {expected_columns}, got {reader.fieldnames}."
)
for row_number, row in enumerate(reader, start=2):
row_count += 1
run_id = row["run_id"].strip()
if re.fullmatch(r"R[0-9]{3}", run_id) is None:
issues.append(issue(row_number, "run_id", run_id, "PATTERN_ERROR"))
elif run_id in seen_run_ids:
issues.append(issue(row_number, "run_id", run_id, "DUPLICATE_VALUE"))
seen_run_ids.add(run_id)
try:
speed = int(row["speed_kmh"])
except ValueError:
issues.append(issue(row_number, "speed_kmh", row["speed_kmh"], "TYPE_ERROR"))
else:
if not 0 <= speed <= 120:
issues.append(issue(row_number, "speed_kmh", row["speed_kmh"], "OUT_OF_RANGE"))
try:
accel = float(row["accel_m_s2"])
except ValueError:
issues.append(issue(row_number, "accel_m_s2", row["accel_m_s2"], "TYPE_ERROR"))
else:
if not -5.0 <= accel <= 5.0:
issues.append(issue(row_number, "accel_m_s2", row["accel_m_s2"], "OUT_OF_RANGE"))
if row["road_surface"] not in {"dry", "wet"}:
issues.append(issue(row_number, "road_surface", row["road_surface"], "ALLOWED_VALUE_ERROR"))
if row["test_status"] not in {"complete", "review"}:
issues.append(issue(row_number, "test_status", row["test_status"], "ALLOWED_VALUE_ERROR"))
OUTPUT_DIR.parent.mkdir(parents=True, exist_ok=True)
OUTPUT_DIR.mkdir()
dictionary_fields = [
"column_name", "meaning", "unit", "type", "allowed_values", "example"
]
with DICTIONARY.open("x", encoding="utf-8", newline="") as stream:
writer = csv.DictWriter(stream, fieldnames=dictionary_fields)
writer.writeheader()
writer.writerows(SPEC)
issue_fields = ["row_number", "column_name", "value", "issue"]
with ISSUES.open("x", encoding="utf-8", newline="") as stream:
writer = csv.DictWriter(stream, fieldnames=issue_fields)
writer.writeheader()
writer.writerows(issues)
print(f"Rows checked: {row_count}.")
print(f"Dictionary columns: {len(SPEC)}.")
print(f"Validation issues: {len(issues)}.")
print(f"Output folder: {OUTPUT_DIR.as_posix()}")
if __name__ == "__main__":
main()
05Compare os problemas de validação esperados
Apenas R005 deve gerar problemas. Como o cabeçalho do CSV está na linha 1, R005 corresponde fisicamente à linha 6 do CSV. Quatro linhas de problemas devem ser gravadas.
06Verifique se o dicionário e os dados continuam alinhados
Confirme que cada coluna do conjunto de dados tenha exatamente uma linha correspondente no dicionário.
Verifique se as unidades físicas estão explícitas para as grandezas medidas.
Confirme que os valores categóricos permitidos usam a mesma grafia e capitalização do conjunto de dados.
Revise cada problema de validação em vez de excluir automaticamente as linhas inválidas.
Execute o script novamente sem alterar OUTPUT_DIR. Ele deve parar com FileExistsError em vez de substituir o dicionário e o relatório anteriores.
Problema
O que verificar
Uma nova coluna do conjunto de dados não tem entrada no dicionário
Atualize o dicionário antes da análise para documentar o significado e a unidade.
O mesmo conceito aparece com unidades diferentes
Use colunas separadas ou padronize explicitamente as unidades; não dependa da memória.
Os rótulos de categoria mudam ao longo do tempo
Defina os valores permitidos e documente adições intencionais, como uma nova condição de via.
A planilha transforma IDs inteiros em números
Armazene os identificadores como strings quando zeros à esquerda ou padrões forem significativos.
A validação passa, mas o significado está errado
Verificações estruturais não conseguem detectar uma definição científica incorreta ou um canal de sensor rotulado incorretamente.
07Expanda o dicionário conforme o projeto crescer
Um dicionário prático de dados de pesquisa frequentemente precisa de mais do que os seis campos mostrados aqui. Dependendo do projeto, adicione source system, sensor location, coordinate direction, sampling rate, nullable status, precision, calculation method, valid range, missing-value code e responsible owner.
Os valores permitidos devem refletir o significado científico, e não simplesmente o mínimo e o máximo observados no momento. Se os valores de speed em um arquivo estiverem entre 30 e 70 km/h, isso não significa automaticamente que 30 a 70 seja o intervalo de engenharia válido.
Versione o dicionário junto com o conjunto de dados ou o código de análise. Se a definição de uma coluna, unidade, convenção de sinal ou categoria mudar, registre quando a alteração ocorreu. Um dicionário de dados é mais útil quando descreve exatamente a versão dos dados que está sendo analisada.
Registro de execução e verificação
2026-09-20 · exemplo verificado manualmente · alvo: Python 3.12 · biblioteca padrão: csv, pathlib, re · sem execução
Foram contadas manualmente 5 linhas sintéticas e 5 colunas do conjunto de dados.
Foi verificado manualmente que R001 a R004 atendem às regras declaradas no dicionário.
Foram identificados quatro problemas em R005: speed 135 acima do intervalo 0-120, valor de accel fast não numérico, road_surface snow não permitido e test_status done não permitido.
Foi confirmado que o próprio R005 corresponde ao padrão de run_id com R seguido de três dígitos.
Foi derivada manualmente a linha física 6 do CSV para todos os quatro problemas de validação de R005.
O script foi inspecionado quanto à verificação exata do cabeçalho, IDs de execução exclusivos, verificações de intervalo numérico, verificações categóricas, proteção contra colisão de saída e preservação do CSV original.
Limites da verificação
O código não foi executado pelo autor desta resposta; nenhum CSV de dicionário ou validação foi criado.
Os intervalos e categorias sintéticos são específicos deste exercício e não representam limites gerais de engenharia automotiva.
O significado científico, a calibração dos sensores, as convenções de coordenadas, as políticas de valores ausentes e o versionamento dos metadados não foram validados automaticamente.
As URLs da documentação oficial foram fornecidas com base em locais de documentação conhecidos, mas não foram verificadas ao vivo.
Em vez de coletar apenas um título e uma URL, registre em uma única linha a data de referência, a data de publicação, a data de acesso, as unidades e os termos de uso. Inclui um modelo CSV e uma checklist que não exigem código.
Separe IDs duplicados de respostas em branco em 10 respostas sintéticas. Informe o denominador das respostas válidas e salve em um novo arquivo as contagens e porcentagens por opção, além dos motivos de exclusão.
Mantenha uma pequena lista de referências de pesquisa em CSV, normalize o texto DOI para comparação e gere um arquivo de revisão para valores DOI duplicados e ausentes. O workflow preserva o CSV original e não afirma que um DOI é válido apenas porque está presente.