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 código 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
ChatGPT Python tool · Python 3.13.5 · standard library: csv, pathlib, re
A execução foi concluída com sucesso para 5 linhas e 5 colunas do dicionário.
O validation_issues.csv gerado continha exatamente 4 linhas, todas referentes à linha física 6 do CSV (R005): speed_kmh 135 OUT_OF_RANGE, accel_m_s2 fast TYPE_ERROR, road_surface snow ALLOWED_VALUE_ERROR e test_status done ALLOWED_VALUE_ERROR.
O validation_issues.csv gerado correspondeu exatamente ao CSV esperado do artigo.
O data_dictionary.csv gerado continha exatamente as 5 linhas SPEC e os valores de metadados esperados.
A saída do console correspondeu exatamente: Rows checked: 5; Dictionary columns: 5; Validation issues: 4; Output folder: outputs/data_dictionary_result.
A segunda execução gerou FileExistsError para outputs/data_dictionary_result, confirmando a proteção contra sobrescrita.
A comparação SHA-256 confirmou que test_runs.csv permaneceu inalterado.
Limites da verificação
O ambiente de execução era Python 3.13.5 em vez do Python 3.12 alvo do artigo.
O ambiente de execução emitiu no stderr um aviso não relacionado de aquecimento do ambiente de planilhas durante a inicialização do Python; isso não afetou a primeira execução bem-sucedida do script, os arquivos gerados nem o teste de proteção contra sobrescrita.
O script verifica apenas as regras declaradas de estrutura, tipo, intervalo e categoria; ele não valida a correção científica das próprias definições de metadados.
Fontes de referência
As explicações e os exemplos são de elaboração própria. Os comportamentos e conceitos relacionados podem ser consultados nas fontes oficiais abaixo.
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.