2025, Oct 17 21:16

Как исправить ошибку Matplotlib: x и y должны совпадать

Разбираем типичную ошибку Matplotlib при построении 1D массива NumPy: x и y разной длины. Поясняем причину, пример с np.arange и советы для временных рядов.

При построении графика одномерного массива NumPy в Matplotlib распространённая ошибка — передавать массивы x и y разной длины. Если они не совпадают, Matplotlib выдаёт понятное исключение: x and y must have the same first dimension. Ниже — минимальный, приближённый к реальности сценарий, который приводит к этой ошибке, и простой способ её исправить.

Постановка задачи

Набор данных содержит 1800 отсчётов АЦП, собранных за 3 минуты с частотой 10 Гц. Задача — прочитать значения из файла, сформировать одномерный массив NumPy и визуализировать его.

import matplotlib.pyplot as plt
import numpy as np
series = np.array
log_path = "MyValues.log"  # Замените на свой путь
samp_rate = 10
span_sec  = 180.0            # секунды
sample_total = int(span_sec * samp_rate)  # ожидаемое число отсчётов
try:
    with open(log_path, 'r') as fh:
        for row in fh:
            series = np.append(series, int(row.strip()))
except FileNotFoundError:
    print(f"Error: The file '{log_path}' was not found.")
except Exception as exc:
    print(f"An error occurred: {exc}")
print(len(series))
plt.figure(figsize=(10, 6))
plt.plot(sample_total, series, marker='o', linestyle='-', color='purple')
plt.title('Plot of 1D Array Data')
plt.xlabel('Index')
plt.ylabel('Value')
plt.grid(True)
plt.xticks(sample_total)
plt.show()

Что пошло не так

В вызове построения графика по оси X передаётся скаляр, а по оси Y — вектор. Matplotlib ожидает, что x и y будут последовательностями одинаковой длины, либо только y — если индексы должны генерироваться автоматически. В нашем случае sample_total равно 1800 — это одно число, а не массив индексов. Та же ошибка повторяется в xticks: туда передаётся одиночное целое вместо набора положений для делений оси.

Иными словами, в y много точек, а x содержит всего одно значение. Несоответствие и вызывает ValueError.

Решение: сформируйте согласованный индекс для оси X

Постройте последовательность для оси X той же длины, что и ваши данные. Если нужен индексный график, используйте np.arange по длине массива. Кроме того, сначала прочитайте файл в числовой вектор, а затем стройте график.

import matplotlib.pyplot as plt
import numpy as np
log_path = "MyValues.log"
samp_rate = 10
span_sec = 180.0
sample_total = int(span_sec * samp_rate)
try:
    with open(log_path, "r") as fh:
        readings = [int(row.strip()) for row in fh]
    data_vec = np.array(readings)
    # Необязательная проверка на соответствие ожидаемому числу отсчётов
    if len(data_vec) != sample_total:
        print(f"Expected {sample_total}, but got {len(data_vec)}")
    x_index = np.arange(len(data_vec))
    plt.figure(figsize=(10, 6))
    plt.plot(x_index, data_vec, marker='o', linestyle='-', color='purple')
    plt.title('Plot of 1D Array Data')
    plt.xlabel('Index')
    plt.ylabel('Value')
    plt.grid(True)
    plt.xticks(x_index)
    plt.show()
except FileNotFoundError:
    print(f"Error: The file '{log_path}' not exist.")
except Exception as err:
    print(f"error occurred: {err}")

Почему это важно

В задачах с временными рядами и обработкой сигналов — например, при просмотре сырых значений АЦП перед проектированием фильтра — график обычно служит первой проверкой здравого смысла. Если ось X не согласована с данными, легко неверно трактовать тренды или вовсе не построить график. Совпадение размеров x и y избавляет от скрытых ловушек при отладке и делает следующие шаги, такие как прототипирование фильтров, гораздо надёжнее. Это также помогает проверить исходные предположения: сравнение ожидаемого числа отсчётов с фактически загруженными быстро выявит пропуски или лишние строки в источнике данных.

Выводы

Всегда передавайте в Matplotlib корректный вектор x, если не используете неявную индексацию. Для индексных графиков достаточно np.arange по длине данных. Если известны частота дискретизации и длительность, заранее сверяйте ожидаемое число отсчётов с загруженными данными — так вы проверите целостность перед визуальным анализом и проектированием фильтров. При таких небольших предохранителях построение становится предсказуемым, а рабочий процесс по обработке сигналов — стабильным.

Статья основана на вопросе с StackOverflow от Nimit Vachhani и ответе от Ranger.