Форматы данных для Radar

Radar-графики в Nivo используют строго определённую структуру данных, основанную на наборах объектов с именованными показателями. Каждая точка на радиальной оси представляет отдельную категорию, а значение внутри объекта определяет величину для этой категории.

Базовая концепция строится вокруг массива объектов, где каждый объект соответствует одной «серии» данных.


Базовый формат данных

Минимальная структура данных для Radar-графика включает:

  • идентификатор серии
  • набор числовых значений по категориям
const data = [
  {
    taste: 80,
    cost: 60,
    depth: 70,
    id: "product A"
  }
]

Каждое поле, кроме id, рассматривается как отдельная ось (axis). В приведённом примере оси: taste, cost, depth.

Ключевым моментом является то, что Nivo автоматически интерпретирует все числовые поля, кроме идентификатора серии, как измерения для радиальной диаграммы.


Множественные серии данных

Radar-графики раскрывают свою основную функциональность при сравнении нескольких объектов. В этом случае структура данных расширяется за счёт добавления дополнительных элементов массива.

const data = [
  {
    taste: 80,
    cost: 60,
    depth: 70,
    id: "product A"
  },
  {
    taste: 65,
    cost: 90,
    depth: 50,
    id: "product B"
  },
  {
    taste: 90,
    cost: 40,
    depth: 80,
    id: "product C"
  }
]

Каждый объект массива формирует отдельный полигон на Radar-графике. Сравнение происходит по одинаковым ключам (taste, cost, depth).


Роль ключа идентификации

Поле id выполняет функцию уникального идентификатора серии. Оно используется для:

  • различения наборов данных
  • отображения легенды
  • стилизации отдельных серий

Отсутствие или дублирование id приводит к некорректному отображению серий.


Формирование осей (keys)

В Nivo Radar явно задаётся список ключей, которые определяют оси графика:

const keys = ["taste", "cost", "depth"]

Эти ключи должны:

  • существовать во всех объектах данных
  • содержать числовые значения
  • быть согласованными между всеми сериями

Несоответствие ключей приводит к пропускам значений или визуальным разрывам полигона.


Числовая природа значений

Radar-график работает исключительно с числовыми значениями. Поддерживаются:

  • целые числа
  • дробные числа
  • нормализованные значения (например, 0–1)

Пример нормализованного набора:

const data = [
  {
    taste: 0.8,
    cost: 0.6,
    depth: 0.7,
    id: "normalized A"
  },
  {
    taste: 0.5,
    cost: 0.9,
    depth: 0.4,
    id: "normalized B"
  }
]

Использование строк или null-значений приводит к игнорированию точки или некорректной отрисовке.


Фиксированный набор ключей и согласованность структуры

Все объекты массива должны иметь одинаковую структуру. Допустимая модель:

[
  { id: "A", x: 10, y: 20, z: 30 },
  { id: "B", x: 15, y: 25, z: 35 }
]

Недопустимая модель:

[
  { id: "A", x: 10, y: 20 },
  { id: "B", x: 15, z: 35 }
]

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


Использование вложенных данных и трансформация

Часто данные приходят в формате, не совместимом с Radar-графиком. Типичный случай — вложенные структуры:

const raw = [
  {
    id: "A",
    stats: {
      taste: 80,
      cost: 60,
      depth: 70
    }
  }
]

Для использования в Nivo требуется трансформация:

const data = raw.map(item => ({
  id: item.id,
  taste: item.stats.taste,
  cost: item.stats.cost,
  depth: item.stats.depth
}))

Динамическое формирование ключей

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

const keys = Object.keys(data[0]).filter(k => k !== "id")

Такой подход требует строгой гарантии однородности объектов массива.


Масштабирование значений

Radar-график может работать с данными разного масштаба, однако визуальная интерпретация зависит от нормализации.

Пример приведения к процентам:

const normalized = data.map(item => ({
  id: item.id,
  taste: item.taste / 100,
  cost: item.cost / 100,
  depth: item.depth / 100
}))

Это позволяет унифицировать отображение при разнородных метриках.


Обработка отсутствующих значений

Отсутствующие значения должны быть явно обработаны:

  • замена на 0
  • замена на среднее значение
  • исключение серии

Пример замены:

const safeData = data.map(item => ({
  id: item.id,
  taste: item.taste ?? 0,
  cost: item.cost ?? 0,
  depth: item.depth ?? 0
}))

Совместимость с конфигурацией Nivo Radar

Структура данных тесно связана с параметрами компонента:

  • indexBy определяет поле идентификатора
  • keys определяет оси
<Radar
  data={data}
  keys={["taste", "cost", "depth"]}
  indexBy="id"
/>

Несоответствие между indexBy и фактическим полем данных приводит к пустой визуализации.


Частые ошибки при подготовке данных

Основные проблемы возникают при:

  • использовании строк вместо чисел
  • несогласованности ключей между объектами
  • отсутствии id
  • наличии лишних вложенных структур без трансформации
  • смешении масштабов значений без нормализации

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


Преобразование табличных данных в Radar-формат

Часто данные поступают в виде таблицы:

const table = [
  ["product A", 80, 60, 70],
  ["product B", 65, 90, 50]
]

Преобразование:

const data = table.map(row => ({
  id: row[0],
  taste: row[1],
  cost: row[2],
  depth: row[3]
}))

Такой подход позволяет интегрировать Radar-графики в аналитические системы с табличным источником данных.


Агрегация данных перед визуализацией

При наличии большого количества исходных записей часто требуется агрегация:

const grouped = Object.values(
  raw.reduce((acc, item) => {
    if (!acc[item.id]) {
      acc[item.id] = { id: item.id, taste: 0, cost: 0, depth: 0, count: 0 }
    }

    acc[item.id].taste += item.taste
    acc[item.id].cost += item.cost
    acc[item.id].depth += item.depth
    acc[item.id].count += 1

    return acc
  }, {})
)

const data = grouped.map(item => ({
  id: item.id,
  taste: item.taste / item.count,
  cost: item.cost / item.count,
  depth: item.depth / item.count
}))

Итоговая модель данных Radar в Nivo

Универсальная форма представления сводится к следующей схеме:

  • массив объектов
  • поле идентификатора серии
  • набор числовых ключей одинаковой структуры
  • согласованный список осей
  • отсутствие вложенности без предварительной трансформации