여러 시험 조건을 같은 시간축에서 비교하기
세 개의 설명용 합성 CSV를 검증한 뒤, 같은 시간 표본과 가속도 단위를 쓰는 곡선을 한 그래프에 겹쳐 그립니다.
설명용 합성 데이터에서 단위, 누락값, 유한수, 시간 중복·역행을 확인하고 점검 결과와 그래프를 저장합니다.
이런 분께자동차 시험 CSV를 처음 파이썬으로 읽어 보는 엔지니어와 입문자
설명용 합성 데이터의 파일 구조, 숫자, 단위, 시간 순서를 먼저 검사합니다. 값이 읽힌다는 사실만으로 단위가 맞거나 시간이 올바르다고 알 수는 없습니다. 이 예제는 모든 입력 행에서 s와 km/h가 명시되어 있는지 확인하고 원본 행 순서대로 시간이 증가하는지 검사합니다.
| 열 | 동봉 값과 의미 |
|---|---|
| dataset_note | 설명용 합성 데이터 |
| time | 0.0부터 1.0까지 경과 시간 |
| time_unit | s |
| speed | 0부터 22까지 속도 값 |
| speed_unit | km/h |
숫자 칸에는 단위 문자열을 붙이지 않습니다. 단위는 별도 열에 기록합니다. time은 음수가 될 수 없고, 최소 두 개의 표본이 필요합니다. speed의 물리적 정상 범위는 이 코드에서 정하지 않습니다.
python --version
python -m pip install -r requirements.txt
python example.py설치는 인터넷 연결이 필요합니다. 코드의 BASE는 현재 터미널 위치가 아니라 example.py의 위치를 기준으로 입력과 결과 경로를 정합니다.
CSV의 각 행을 읽으면서 누락값과 단위를 확인합니다. math.isfinite로 NaN과 무한대를 거부합니다. 현재 시간이 직전 시간보다 작거나 같으면 중지하므로, 정렬해서 문제를 숨기거나 중복 표본을 임의로 지우지 않습니다. 입력 검사가 끝난 후에만 outputs를 만듭니다.
"""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
outputs/data_check.json에는 단위와 표본 수, 시간 범위, 표본 간격의 최솟값·최댓값이 기록됩니다. outputs/synthetic_speed.png는 같은 설명용 합성 데이터를 그린 결과입니다.
| 항목 | 동봉 설명용 합성 데이터 결과 |
|---|---|
| 표본 수 | 6 |
| 시간 범위 | 0.0~1.0 s |
| 표본 간격 | 약 0.2 s |
| 속도 최솟값 / 최댓값 | 0 / 22 km/h |
| 시간 증가 여부 | true |

JSON의 표본 간격은 부동소수점 표현 때문에 0.19999999999999996처럼 보일 수 있습니다. 입력 값의 정확도나 계측 분해능을 추가로 주장하는 숫자는 아닙니다.
| 메시지 | 원본에서 확인할 것 |
|---|---|
| expected units s and km/h | 내보내기 설정과 각 행의 단위가 일치하는지 확인합니다. 코드가 자동 환산하지 않습니다. |
| duplicate or decreasing time | 재시작·표본 중복·파일 합치기 과정에서 시간 순서가 달라졌는지 확인합니다. |
| NaN and infinite values | 누락 표본이나 계산 오류를 원본에서 확인합니다. |
| synthetic-data label is required | 이 튜토리얼 전용 설명용 합성 데이터 표시를 유지합니다. |
| missing or extra field | 쉼표 수, 빈 칸, 열 이름을 확인합니다. |
Windows 11 (10.0.26200), CPython 3.12.14 (64비트). openpyxl 3.1.5, Matplotlib 3.10.8. 예제별 사용 라이브러리는 requirements.txt에 고정했습니다.
코드·입력 데이터·실행 안내가 포함되어 있습니다. 압축을 풀고 README.txt부터 읽어 주세요.
예제 ZIP 다운로드직접 작성한 연습 자료 · 원본을 따로 보관한 뒤 실행하세요.
설명과 예제는 직접 작성했습니다. 관련 동작과 개념은 아래 공식 자료에서 확인할 수 있습니다.