自動車・データ実務

複数の試験条件を同じ時間軸で比較する

3つの合成デモ CSV ファイルを検証し、同じ時刻サンプルと加速度単位を共有する曲線を1つのグラフに重ねて表示します。

目次を表示

この翻訳はAIで作成しました。コード、単位、数値は原文と併せて確認してください。各言語のネイティブ話者による校閲は、まだ完了していません。 English

対象読者複数条件の試験結果を重ねて比較したい自動車分野の Python 初学者

準備するもの
  • Python 3.12 とターミナルを用意します。python --version でバージョンを確認してください。
  • ダウンロードした ZIP 全体を展開し、example.py があるフォルダでターミナルを開きます。
  • まず付属の練習データから始め、その後で結果を元ファイルと比較します。
  • inputs フォルダ内の case_a.csv, case_b.csv, case_c.csv はすべて合成デモデータです。
  • すべての入力で time は s、acceleration は m/s^2 を使用し、time samples も同じです。

01比較に必要な条件をそろえる

複数の曲線を1つのグラフに重ねるには、time と縦軸の units が同じ意味を持っている必要があります。この例では、合成デモデータ Case A, Case B, Case C を、time は s、acceleration は m/s^2 の共通軸上に描画します。condition 名は各ファイルの condition 列から読み取ります。

02フォルダと入力形式を準備する

スクリプトは inputs フォルダ内の .csv ファイルを名前順に読み取ります。ファイルは少なくとも2つ必要で、各ファイルには1つの condition だけを含める必要があります。すべての行には dataset_note, condition, time, time_unit, acceleration, acceleration_unit の6列が必要です。

フィールド付属例
dataset_noteSynthetic demonstration data
conditionCase A (ASCII letters and numbers)
time / time_unit0.0 / s
acceleration / acceleration_unit0.8 / m/s^2

この例では、各ファイルの time arrays が完全に同じ場合だけ比較します。sample 数、開始時刻、またはいずれかの time value が異なる場合は停止します。グラフの軸には共有単位として m/s² を表示します。

03ファイルを準備して例を実行する

  1. ZIP を展開し、README.txt に記載された入力ファイルが example.py と同じフォルダにあることを確認します。ZIP アーカイブ内から直接実行しないでください。
  2. example.py があるフォルダで、以下のコマンドを1行ずつ実行します。Windows で python が使えず py が使える場合は、各コマンドの python を py -3.12 に置き換えます。
  3. 完了メッセージが表示されたら、新しい outputs フォルダを開きます。outputs がすでに存在する場合は、以前の結果を保持するために先に名前を変更してから、もう一度実行します。
bash
python --version
python -m pip install -r requirements.txt
python example.py

インストールにはインターネット接続が必要です。コード内の BASE は、現在のターミナルフォルダではなく example.py を基準に入力・出力パスを設定します。

04完全なコードと比較前チェック

各ファイルの time order と units を確認した後、condition 名の重複を確認します。その後、残りの arrays を最初のファイルの time array と比較し、すべて一致する場合だけ1つの Axes に線を追加します。sorting, time shifting, interpolation, unit conversion は自動では行いません。

example.py
"""Overlay explanatory synthetic test conditions on the same axes.

All files must have the same explicit units and matching time samples.
No interpolation, clock shifting, filtering, or safety assessment is performed.
"""
import csv
import math
from pathlib import Path

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

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


def read_condition(path):
    times, values = [], []
    label = None
    with path.open(encoding="utf-8-sig", newline="") as file:
        reader = csv.DictReader(file)
        if reader.fieldnames != HEADERS:
            raise ValueError(f"{path.name}: 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"{path.name}:{line}: missing or extra field.")
            if row["dataset_note"] != NOTE:
                raise ValueError(f"{path.name}:{line}: synthetic-data label is required.")
            if row["time_unit"] != "s" or row["acceleration_unit"] != "m/s^2":
                raise ValueError(f"{path.name}:{line}: expected units s and m/s^2; no automatic conversion.")
            if not row["condition"].isascii():
                raise ValueError(f"{path.name}:{line}: use an ASCII condition label for portable plotting.")
            label = row["condition"] if label is None else label
            if row["condition"] != label:
                raise ValueError(f"{path.name}:{line}: condition label changes within one file.")
            time, value = float(row["time"]), float(row["acceleration"])
            if not math.isfinite(time) or not math.isfinite(value) or time < 0:
                raise ValueError(f"{path.name}:{line}: expected finite values and nonnegative time.")
            if times and time <= times[-1]:
                raise ValueError(f"{path.name}:{line}: duplicate or decreasing time.")
            times.append(time)
            values.append(value)
    if len(times) < 2:
        raise ValueError(f"{path.name}: at least two samples are required.")
    return label, times, values


def main():
    destination = BASE / "outputs"
    if destination.exists():
        raise ValueError("outputs already exists; rename it before running again.")
    paths = sorted((BASE / "inputs").glob("*.csv"))
    if len(paths) < 2:
        raise ValueError("At least two CSV files are required in inputs.")
    conditions = [read_condition(path) for path in paths]
    if len({label for label, _, _ in conditions}) != len(conditions):
        raise ValueError("Condition labels must be unique across files.")
    reference_times = conditions[0][1]
    if any(times != reference_times for _, times, _ in conditions[1:]):
        raise ValueError("Time samples do not match; check alignment before comparison.")

    figure, axis = plt.subplots(figsize=(8, 4.6), layout="constrained")
    for label, times, values in conditions:
        axis.plot(times, values, marker="o", linewidth=2, label=label)
    axis.set(title="Test conditions | Explanatory synthetic data", xlabel="Elapsed time (s)", ylabel="Acceleration (m/s²)")
    axis.spines[["top", "right"]].set_visible(False)
    axis.grid(alpha=0.2)
    axis.legend(frameon=False)
    destination.mkdir(exist_ok=False)
    with (destination / "comparison_summary.csv").open("x", encoding="utf-8-sig", newline="") as file:
        writer = csv.writer(file)
        writer.writerow(["dataset_note", "condition", "sample_count", "min_acceleration", "max_acceleration", "unit"])
        for label, _, values in conditions:
            writer.writerow([NOTE, label, len(values), min(values), max(values), "m/s^2"])
    figure.savefig(destination / "synthetic_comparison.png", dpi=160)
    plt.close(figure)
    print(f"Explanatory synthetic data: {len(conditions)} conditions, {len(reference_times)} matching time samples each.")
    print("Created outputs/comparison_summary.csv and outputs/synthetic_comparison.png.")


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

05グラフと summary CSV を確認する

3つの conditions は outputs/synthetic_comparison.png に重ねて表示されます。outputs/comparison_summary.csv には、各 condition の samples 数と acceleration の minimum, maximum が保存されます。これらの数値は合成デモデータの簡単な要約です。

ConditionSamplesMinimumMaximum
Case A60.0 m/s²1.4 m/s²
Case B60.0 m/s²1.1 m/s²
Case C60.0 m/s²1.7 m/s²
Acceleration comparison of synthetic demonstration data Cases A, B, and C. Three curves using the same 0–1 s time and m/s² axes.
Acceleration comparison of synthetic demonstration data Cases A, B, and C. Three curves using the same 0–1 s time and m/s² axes.

0.4 s の sample では、3本の曲線の値は 1.4, 1.1, 1.7 m/s² です。グラフの線は samples 間を接続しているだけで、その間に新しい measured values を作成するものではありません。

06軸が一致していることを確認する手順

  1. グラフ legend の Case A, Case B, Case C が入力ファイルの condition values と一致していることを確認します。
  2. x-axis が Elapsed time (s)、y-axis が Acceleration (m/s²) であることを確認します。
  3. 0.4 s における3つの CSV ファイルの値を、グラフと summary table と比較します。
  4. 新しい練習用コピーで case_b.csv の time value を1つ 0.41 に変更します。Time samples do not match というメッセージで停止することを確認します。
  5. 別の新しいコピーで acceleration_unit を g に変更し、自動変換せずに停止することを確認します。

07比較が停止する理由を確認する

メッセージ確認すること
expected units s and m/s^2exported file の実際の units と表記を確認します。
duplicate or decreasing timeそのファイルと行の time order を確認します。
Time samples do not match開始時刻、sampling interval、missing samples を確認します。原因を把握せずに times を単純に上書きしないでください。
Condition labels must be unique各ファイルで異なる condition name を使用します。
condition label changes1つのファイルに複数の conditions が混在していないか確認します。
At least two CSV files入力ファイルが inputs フォルダにあることを確認します。

08グラフだけでは分からないこと

  • 数値上の time axis が同じでも、trigger または reference time が異なる場合があります。実際の試験では alignment の基準を別途確認してください。
  • 完全に同一の time arrays だけを許可します。approximate matching, resampling, interpolation, time-delay correction は対象外です。
  • 異なる sensor locations, coordinate systems, sampling filters, test conditions が比較可能かどうかをコードは判断しません。
  • sample maximum は samples 間の真の maximum を保証しません。このグラフは pass/fail、performance ranking、安全性判断を提供しません。

実行・検証の記録

Windows 11 (10.0.26200), CPython 3.12.14 (64-bit). openpyxl 3.1.5, Matplotlib 3.10.8. 各例で使用するライブラリは requirements.txt に固定されています。

  • 3 conditions × 6 samples の合成デモデータと minimum, maximum values を確認しました
  • unit mismatch、duplicate または reversed times、mismatched time arrays、duplicate condition names に対するエラーを確認しました
  • 元ファイルの hashes が変更されていないこと、既存 outputs が拒否されること、PNG が作成されることを確認しました
検証範囲の限界
  • 実際の test conditions の比較可能性、time synchronization、measurement uncertainty、安全性は評価していません。

サイト全体の執筆・検証方針

自分で実行するためのサンプルファイル

コード、入力データ、実行手順が含まれています。展開して、まずREADME.txtを読んでください。

サンプルZIPをダウンロード

サンプルコード、ファイル名、入力キーは原文のままです。翻訳本文のコマンドと確認手順も併せて参照してください。

独自に作成した練習用資料 · 元のファイルを別に保管してから実行してください。

参考資料

説明と例は独自に作成しました。関連する動作や概念は、以下の公式資料で確認できます。