Pesquisa e fontes

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.

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.

csv
run_id,speed_kmh,accel_m_s2,road_surface,test_status
R001,30,0.5,dry,complete
R002,50,-1.2,wet,complete
R003,70,0.0,dry,review
R004,40,-0.8,wet,complete
R005,135,fast,snow,done

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_namesignificadounidadetipovalores permitidosexemplo
run_idIdentificador exclusivo de uma execução de testestringR seguido de exatamente 3 dígitos; exclusivoR001
speed_kmhVelocidade do veículo no início do registrokm/hinteiro0 a 120 inclusive50
accel_m_s2Aceleração longitudinalm/s^2ponto flutuante-5.0 a 5.0 inclusive-1.2
road_surfaceCondição da superfície da via usada no testecategoriadry;wetwet
test_statusEstado de revisão do registro de testecategoriacomplete;reviewcomplete

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.

csv
row_number,column_name,value,issue
6,speed_kmh,135,OUT_OF_RANGE
6,accel_m_s2,fast,TYPE_ERROR
6,road_surface,snow,ALLOWED_VALUE_ERROR
6,test_status,done,ALLOWED_VALUE_ERROR

A saída esperada do console abaixo foi derivada manualmente a partir do conjunto de dados sintético e do script. Não é um log capturado de execução.

text
Rows checked: 5.
Dictionary columns: 5.
Validation issues: 4.
Output folder: outputs/data_dictionary_result

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.
ProblemaO que verificar
Uma nova coluna do conjunto de dados não tem entrada no dicionárioAtualize o dicionário antes da análise para documentar o significado e a unidade.
O mesmo conceito aparece com unidades diferentesUse colunas separadas ou padronize explicitamente as unidades; não dependa da memória.
Os rótulos de categoria mudam ao longo do tempoDefina os valores permitidos e documente adições intencionais, como uma nova condição de via.
A planilha transforma IDs inteiros em númerosArmazene os identificadores como strings quando zeros à esquerda ou padrões forem significativos.
A validação passa, mas o significado está erradoVerificaçõ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.

Princípios de redação e verificação de todo o site

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.