repeat: повторение по полям

Повторение по полям в Vega-Lite является механизмом генерации множественных визуализаций на основе набора полей данных без необходимости ручного дублирования описания графика. Концепция repeat позволяет декларативно задавать матрицу графиков, где каждая ячейка соответствует отдельному полю или комбинации полей, а структура визуализации остаётся единой.

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

В системе Vega и её упрощённом диалекте Vega-Lite повторение относится к уровню top-level spec и тесно связано с компоновкой (layout composition). Repeat не является трансформацией данных в классическом смысле; это механизм генерации нескольких view.

Ключевые формы repeat:

  • повторение по строкам (row)
  • повторение по колонкам (column)
  • комбинированная сетка (row × column)
  • повторение внутри encoding через ссылку на текущий элемент

Базовая структура repeat

Типовая структура repeat задаётся следующим образом:

{
  "data": {"url": "data.csv"},
  "repeat": {
    "column": ["A", "B", "C"]
  },
  "spec": {
    "mark": "line",
    "encoding": {
      "x": {"field": "date", "type": "temporal"},
      "y": {"field": {"repeat": "column"}, "type": "quantitative"}
    }
  }
}

Здесь ключевой элемент:

{"field": {"repeat": "column"}}

Он указывает, что значение поля будет подставляться из текущего элемента массива column.

Повторение по строкам и колонкам

Колонное повторение

Колонное повторение создаёт набор графиков, размещённых горизонтально. Каждая колонка соответствует одному полю.

"repeat": {
  "column": ["sales", "profit", "discount"]
}

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

Строчное повторение

Строчное повторение размещает графики вертикально:

"repeat": {
  "row": ["q1", "q2", "q3", "q4"]
}

Обычно применяется для временных сегментов или категориальных разрезов.

Двумерное повторение

Комбинация:

"repeat": {
  "row": ["A", "B"],
  "column": ["X", "Y", "Z"]
}

Создаёт матрицу 2×3, где каждая ячейка соответствует паре (row, column).

Повторение внутри encoding

Наиболее важная часть механизма — использование repeat внутри encoding.

"encoding": {
  "y": {"field": {"repeat": "row"}, "type": "quantitative"},
  "x": {"field": "year", "type": "temporal"}
}

Здесь:

  • repeat: "row" — подставляет текущий элемент из списка row
  • repeat: "column" — аналогично для колонок

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

Семантика подстановки полей

При компиляции спецификации Vega-Lite происходит разворачивание repeat в набор независимых view.

Алгоритм:

  1. Берётся массив полей из repeat.row и repeat.column
  2. Формируется декартово произведение (если есть оба измерения)
  3. Для каждой комбинации создаётся экземпляр spec
  4. В encoding подставляются конкретные значения field

Результат эквивалентен множеству отдельных графиков, но описан декларативно.

Сравнение repeat и facet

Несмотря на схожесть, repeat и facet имеют принципиальные различия.

facet

Facet группирует данные по значению поля:

"facet": {
  "row": {"field": "category", "type": "nominal"}
}

Особенность:

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

repeat

Repeat работает с именами полей:

"repeat": {
  "row": ["sales", "profit"]
}

Особенность:

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

Таким образом:

  • facet = разбиение по данным
  • repeat = разбиение по структуре данных

Практическая модель данных для repeat

Repeat особенно эффективен, когда данные имеют широкий формат:

date sales profit cost

В таком случае удобно:

"repeat": {
  "column": ["sales", "profit", "cost"]
}

И избежать преобразования в длинный формат.

Если данные уже находятся в long format, repeat становится менее естественным и чаще заменяется facet или transform.

Повторение и масштабирование осей

Каждый повторяемый график может иметь независимые оси или общие шкалы.

Независимые шкалы

"resolve": {
  "scale": {
    "y": "independent"
  }
}

Это позволяет каждой панели иметь собственный диапазон значений.

Общие шкалы

"resolve": {
  "scale": {
    "y": "shared"
  }
}

Используется для прямого сравнения между графиками.

Использование repeat с mark-композициями

Repeat совместим со всеми базовыми mark-типами:

  • line
  • bar
  • area
  • point
  • tick

Пример линейного повторения:

{
  "data": {"url": "stocks.csv"},
  "repeat": {
    "column": ["AAPL", "GOOG", "MSFT"]
  },
  "spec": {
    "mark": "line",
    "encoding": {
      "x": {"field": "date", "type": "temporal"},
      "y": {"field": {"repeat": "column"}, "type": "quantitative"}
    }
  }
}

Каждая линия отображает отдельный временной ряд.

Вложенные структуры repeat

Repeat может использоваться в сочетании с другими композиционными операциями, например facet + layer, но имеет ограничения:

  • нельзя напрямую вкладывать repeat в facet без преобразования
  • layer внутри repeat работает на уровне каждого экземпляра spec
  • concat-подобные конструкции требуют resolve правил

Типичные ошибки при использовании repeat

Несоответствие полей данных

Если поле отсутствует:

"repeat": {
  "column": ["missing_field"]
}

результат — пустая визуализация.

Смешение типов данных

Repeat не проверяет семантику полей. Если одно поле количественное, другое категориальное, но используется одинаковый mark, результат может быть визуально некорректным.

Игнорирование масштабов

Без resolve.scale панели могут интерпретировать данные по-разному, что затрудняет сравнение.

Repeat как механизм шаблонизации

С точки зрения архитектуры спецификации repeat является формой compile-time макроса:

  • вход: шаблон spec + список полей
  • выход: массив независимых view
  • цель: устранение дублирования декларации

Это делает repeat ключевым инструментом при построении аналитических панелей.

Взаимодействие repeat с интерактивностью

При добавлении интерактивных элементов (selection, filter) поведение зависит от области действия:

  • selection внутри repeat применяется локально к каждой панели
  • global selection требует явного определения resolve
  • фильтры могут быть как общими, так и панельными

Пример:

"selection": {
  "brush": {"type": "interval"}
}

В repeat каждая панель получает собственный brush, если не задано иное разрешение.

Производительность и масштабирование

Repeat увеличивает количество view линейно:

  • 3 поля → 3 графика
  • 10×5 → 50 графиков

Это важно учитывать при:

  • больших наборах данных
  • сложных mark-композициях
  • интерактивных дашбордах

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

Структурные паттерны использования

Паттерн сравнения метрик

Используется для сравнения показателей:

  • выручка
  • прибыль
  • расходы

Паттерн временных срезов

Используется для анализа периодов:

  • кварталы
  • годы
  • месяцы

Паттерн многомерной диагностики

Матрица повторений применяется для анализа взаимосвязей переменных.

Итоговая модель поведения repeat

Поведение repeat можно формализовать как функцию:

  • вход: список полей F = {f1, f2, …, fn}
  • шаблон spec S
  • результат: множество спецификаций {S(f1), S(f2), …, S(fn)}

Где S(fi) — это подстановка field = fi во все выражения repeat внутри encoding.

Такой подход делает repeat фундаментальным механизмом декларативной генерации визуализаций в экосистеме Vega-Lite.