Automotive & data work

Check the time axis and units of a test CSV first

Check units, missing values, finite numbers, and duplicate or reversed timestamps in synthetic demonstration data, then save the check results and a chart.

Show contents

This translation was generated by AI. Check the code, units, and numbers against the original. Native-speaker review has not yet been completed for each language. 한국어

Who this is forEngineers and beginners reading a vehicle test CSV with Python for the first time

What you need
  • Have Python 3.12 and a terminal ready. Check the version with python --version.
  • Extract the entire downloaded ZIP and open a terminal in the folder containing example.py.
  • Start with the included practice data, then compare the results with the original files.
  • The included synthetic_test.csv is synthetic demonstration data. It uses s for time and km/h for speed.

01Four things to check before charting

First check the file structure, numbers, units, and time order of the synthetic demonstration data. Being able to read the values does not tell you that the units are right or the times are correct. This example checks that s and km/h are stated in every input row and that time increases in the original row order.

02Read the input CSV

ColumnIncluded values and meaning
dataset_noteSynthetic demonstration data
timeElapsed time from 0.0 to 1.0
time_units
speedSpeed values from 0 to 22
speed_unitkm/h

Do not attach unit strings to numeric cells. Record units in a separate column. time cannot be negative, and at least two samples are required. This code does not define a physically normal range for speed.

03Prepare the files and run the example

  1. Extract the ZIP and check that the input file listed in README.txt is in the same folder as example.py. Do not run the example from inside the ZIP archive.
  2. Run the commands below one line at a time in the folder containing example.py. On Windows, if python is unavailable but py is available, replace python in each command with py -3.12.
  3. After the completion message appears, open the new outputs folder. If outputs already exists, first rename it to keep the previous results, then run the example again.
bash
python --version
python -m pip install -r requirements.txt
python example.py

Installation requires an internet connection. BASE in the code sets the input and output paths relative to example.py, not the current terminal folder.

04Full code and stop conditions

While reading each row of the CSV, it checks for missing values and units. math.isfinite rejects NaN and infinity. If the current time is less than or equal to the previous time, it stops, so it does not hide problems by sorting or arbitrarily delete duplicate samples. outputs is created only after the input check is finished.

example.py
"""Check time order and declared units in explanatory synthetic test data.

This demonstrates file checks only. It makes no vehicle safety assessment.
"""
import csv
import json
import math
from pathlib import Path

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

BASE = Path(__file__).resolve().parent
HEADERS = ["dataset_note", "time", "time_unit", "speed", "speed_unit"]
NOTE = "설명용 합성 데이터"


def read_samples():
    samples = []
    with (BASE / "synthetic_test.csv").open(encoding="utf-8-sig", newline="") as file:
        reader = csv.DictReader(file)
        if reader.fieldnames != HEADERS:
            raise ValueError(f"Expected headers: {HEADERS}")
        for line, row in enumerate(reader, start=2):
            if None in row or any(value is None or not value.strip() for value in row.values()):
                raise ValueError(f"Row {line}: missing or extra field.")
            if row["dataset_note"] != NOTE:
                raise ValueError(f"Row {line}: explanatory synthetic-data label is required.")
            if row["time_unit"] != "s" or row["speed_unit"] != "km/h":
                raise ValueError(f"Row {line}: expected units s and km/h; no automatic conversion.")
            time, speed = float(row["time"]), float(row["speed"])
            if not math.isfinite(time) or not math.isfinite(speed):
                raise ValueError(f"Row {line}: NaN and infinite values are not supported.")
            if time < 0:
                raise ValueError(f"Row {line}: elapsed time must be nonnegative.")
            if samples and time <= samples[-1][0]:
                raise ValueError(f"Row {line}: duplicate or decreasing time; check the source.")
            samples.append((time, speed))
    if len(samples) < 2:
        raise ValueError("At least two samples are required.")
    return samples


def main():
    destination = BASE / "outputs"
    if destination.exists():
        raise ValueError("outputs already exists; rename it before running again.")
    samples = read_samples()
    times, speeds = zip(*samples)
    intervals = [right - left for left, right in zip(times, times[1:])]
    report = {
        "dataset_note": NOTE,
        "scope": "File structure and numeric checks only; no vehicle safety assessment.",
        "sample_count": len(samples), "time_unit": "s", "speed_unit": "km/h",
        "start_time": times[0], "end_time": times[-1],
        "min_interval_s": min(intervals), "max_interval_s": max(intervals),
        "min_speed_kmh": min(speeds), "max_speed_kmh": max(speeds),
        "time_strictly_increasing": True,
    }
    figure, axis = plt.subplots(figsize=(8, 4.6), layout="constrained")
    axis.plot(times, speeds, "o-", color="#2B6578", linewidth=2)
    axis.set(title="Speed trace | Explanatory synthetic data", xlabel="Elapsed time (s)", ylabel="Speed (km/h)")
    axis.spines[["top", "right"]].set_visible(False)
    axis.grid(alpha=0.2)
    destination.mkdir(exist_ok=False)
    with (destination / "data_check.json").open("x", encoding="utf-8") as file:
        json.dump(report, file, ensure_ascii=False, indent=2)
    figure.savefig(destination / "synthetic_speed.png", dpi=160)
    plt.close(figure)
    print(f"Explanatory synthetic data: {len(samples)} samples, {times[0]:g}-{times[-1]:g} s.")
    print(f"Sample interval: {min(intervals):g}-{max(intervals):g} s; units: s, km/h.")
    print("Created outputs/data_check.json and outputs/synthetic_speed.png.")


if __name__ == "__main__":
    try:
        main()
    except (OSError, ValueError, csv.Error) as error:
        raise SystemExit(f"Stopped: {error}") from error

05Check the results and chart

outputs/data_check.json records the units, number of samples, time range, and the minimum and maximum sampling interval. outputs/synthetic_speed.png is a chart of the same synthetic demonstration data.

ItemResults for the included synthetic demonstration data
Samples6
Time range0.0~1.0 s
Sampling intervalAbout 0.2 s
Speed minimum / maximum0 / 22 km/h
Time increasingtrue
Speed curve of synthetic demonstration data. Time 0–1 s, speed 0–22 km/h.
Speed curve of synthetic demonstration data. Time 0–1 s, speed 0–22 km/h.

Because of floating-point representation, the sampling interval in the JSON may appear as 0.19999999999999996. It is not a number that claims any additional precision of the input values or measurement resolution.

06Insert errors yourself to test

  1. Check that sample_count in the normal result is 6 and time_unit is s.
  2. In a freshly extracted practice folder, change the time of the third data row to equal the previous value, 0.2. When run, it should stop with the message duplicate or decreasing time.
  3. In another fresh copy, change one speed_unit to m/s. Check that the expected units message appears and outputs is not created.
  4. Keep the original input file, and run error experiments only on copies.

07What to look at when the check stops

MessageWhat to check in the original
expected units s and km/hCheck that the export settings match the units in each row. The code does not convert automatically.
duplicate or decreasing timeCheck whether the time order changed during a restart, duplicate samples, or file merging.
NaN and infinite valuesCheck the original for missing samples or calculation errors.
synthetic-data label is requiredKeep the label marking it as synthetic demonstration data for this tutorial only.
missing or extra fieldCheck the number of commas, blank cells, and column names.

08What still needs checking after the check passes

  • It does not enforce a rule that the time interval must be constant. If min_interval_s and max_interval_s differ, check the original's sampling period separately.
  • It does not perform filtering, interpolation, unit conversion, sensor calibration, time synchronization, or noise judgments.
  • It checks only the notation in the unit columns. It cannot confirm that the actual values were measured in that unit or that the sensor is on the right channel.
  • This is file-handling practice limited to the included data. Do not interpret it as a validation tool that can be used for real vehicle test procedures or safety judgments.

Execution and verification record

Windows 11 (10.0.26200), CPython 3.12.14 (64-bit). openpyxl 3.1.5, Matplotlib 3.10.8. The libraries used by each example are pinned in requirements.txt.

  • Checked 6 samples of synthetic demonstration data, the time range, units, and intervals
  • Checked errors for unit mismatch, duplicate or reversed times, NaN, and missing values
  • Checked that the original hash is unchanged, existing results are refused, and the PNG is created
Verification limits
  • Only synthetic demonstration data was checked. Real measurement data and vehicle safety were not evaluated.

Site-wide writing and verification principles

Example files to run yourself

Includes code, input data, and instructions. Extract the ZIP and read README.txt first.

Download example ZIP

Example code, filenames, and input keys remain unchanged. Refer to the commands and checking steps in the translated article as well.

References

The explanations and examples were written for this site. See the official sources below for the related behavior and concepts.