Форматы данных: дата-значение

Визуализации временных рядов в Nivo опираются на строго структурированные наборы данных, где каждое наблюдение представлено парой «дата — значение». Такой формат используется в линейных графиках, областных диаграммах и ряде комбинированных представлений, работающих с непрерывной временной шкалой.

Базовая структура данных

Основной принцип — каждое измерение представляет собой объект с полями, фиксирующими момент времени и числовую величину.

Типовая структура:

const data = [
  {
    id: "series-1",
    data: [
      { x: "2024-01-01", y: 10 },
      { x: "2024-01-02", y: 15 },
      { x: "2024-01-03", y: 7 }
    ]
  }
];

Поле x отвечает за временную координату, y — за числовое значение. Несмотря на то, что x выглядит как строка, внутри системы визуализации она преобразуется в временную шкалу при корректной конфигурации осей.

Поддерживаемые типы даты

Nivo опирается на механизмы масштабирования времени из D3, поэтому формат x может принимать несколько вариантов:

ISO 8601 строки

{ x: "2024-03-10T12:00:00Z", y: 42 }

Наиболее универсальный формат, обеспечивающий корректную интерпретацию временных зон и точности до секунд и миллисекунд.

Дата как строка без времени

{ x: "2024-03-10", y: 42 }

Используется для дневных агрегаций, где временная часть не имеет значения.

JavaScript Date объект

{ x: new Date(2024, 2, 10), y: 42 }

Подходит для предварительной обработки данных на стороне приложения, но требует осторожности при сериализации и передаче через API.

Нормализация временной шкалы

При использовании временных данных ключевую роль играет настройка оси X:

xScale: {
  type: "time",
  format: "%Y-%m-%d",
  useUTC: false,
  precision: "day"
}

Параметр type: "time" активирует интерпретацию значений как временной шкалы. Формат задаёт способ парсинга строк, а precision определяет уровень детализации — от года до миллисекунд.

Преобразование данных перед визуализацией

Часто исходные данные приходят в виде плоского массива:

const raw = [
  { date: "2024-01-01", value: 10, series: "A" },
  { date: "2024-01-01", value: 20, series: "B" }
];

Для Nivo требуется группировка по сериям:

const formatted = Object.values(
  raw.reduce((acc, item) => {
    if (!acc[item.series]) {
      acc[item.series] = { id: item.series, data: [] };
    }

    acc[item.series].data.push({
      x: item.date,
      y: item.value
    });

    return acc;
  }, {})
);

Такая структура обеспечивает корректное построение многолинейных графиков.

Сортировка временных значений

Корректная визуализация временных рядов требует строгого упорядочивания по возрастанию даты:

series.data.sort((a, b) => new Date(a.x) - new Date(b.x));

Отсутствие сортировки приводит к искажениям линий, особенно при использовании интерполяции и сглаживания.

Обработка пропусков во времени

Временные ряды часто содержат пропущенные значения. В Nivo такие случаи интерпретируются в зависимости от конфигурации:

  • null или undefined — разрыв линии
  • отсутствие точки — игнорирование интерполяции

Пример:

{ x: "2024-01-02", y: null }

Линия будет разорвана в месте отсутствующего значения, что важно для аналитических графиков.

Масштабирование временных интервалов

При работе с разреженными или плотными данными используется автоматическое масштабирование:

xScale: {
  type: "time",
  min: "auto",
  max: "auto"
}

Автоматический режим позволяет адаптировать отображение под диапазон данных без ручной настройки границ.

Форматирование отображаемых дат

Отображение оси X регулируется через форматтеры:

axisBottom: {
  format: "%b %d",
  tickValues: "every 2 days"
}

Форматы поддерживают спецификацию d3-time-format, где:

  • %Y — год
  • %m — месяц
  • %d — день
  • %H — час
  • %M — минута

Проблемы часовых поясов

При работе с временными данными часто возникает расхождение между локальным временем и UTC.

Использование:

useUTC: true

обеспечивает единообразную интерпретацию дат независимо от среды выполнения. При false применяется локальная временная зона браузера.

Агрегация данных по времени

Для плотных временных рядов применяется агрегация:

const grouped = d3.rollups(
  data,
  v => d3.mean(v, d => d.y),
  d => d.date.slice(0, 10)
);

Результат преобразуется в формат:

{ x: "2024-01-01", y: 12.5 }

Такая подготовка снижает нагрузку на рендеринг и повышает читаемость графиков.

Интерполяция временных рядов

При построении линий между точками используется интерполяция:

  • linear — прямые сегменты
  • monotoneX — сглаживание без выхода за пределы значений
  • basis — кривые Безье

Выбор интерполяции влияет на визуальное восприятие временной динамики и может искажать или подчёркивать тренды.

Типичные ошибки структуры дата–значение

Нарушения формата приводят к некорректному отображению:

  • использование несортированных дат
  • смешение строк и Date объектов в одном наборе
  • отсутствие единообразного формата времени
  • передача числовых timestamp без преобразования шкалы

Корректная структура требует единообразия типа x во всех точках серии.

Работа с timestamp

Вместо строк часто используются числовые временные метки:

{ x: 1710000000000, y: 18 }

В таком случае шкала должна быть настроена соответствующим образом:

xScale: {
  type: "time",
  format: "native"
}

Использование timestamp ускоряет обработку больших массивов данных и снижает накладные расходы на парсинг дат.