Поле format: форматирование меток

В спецификациях Vega-Lite форматирование числовых и временных значений централизовано через механизм format, который применяется к подписям осей, значениям в текстовых марках, всплывающим подсказкам и отдельным элементам представления данных. Поведение format опирается на соглашения библиотеки D3 (в частности, d3-format и d3-time-format), но инкапсулировано в декларативной модели Vega-Lite.

Общая роль format в системе отображения данных

Поле format отвечает за преобразование «сырых» значений данных в человекочитаемое представление без изменения исходного набора данных. Это принципиально важно для декларативной визуализации: данные остаются неизменными, изменяется только их отображение.

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

  • оси (axis.format)
  • подписи текстовых маркеров (encoding.text.format)
  • всплывающие подсказки (tooltip.format)
  • легенды (в ограниченных случаях через scale/labelFormat)
  • временные шкалы (через timeUnit и format)

Синтаксис format для числовых значений

Числовой формат основан на спецификации d3-format. Формат задаётся строкой:

{
  "type": "quantitative",
  "field": "value",
  "format": ".2f"
}

Наиболее распространённые шаблоны:

  • .2f — фиксированное число с 2 знаками после запятой
  • .0f — округление до целого
  • .2% — процентное отображение
  • ,.2f — разделение тысяч
  • $.2f — денежный формат (с символом валюты)
  • .2e — экспоненциальная запись

Пример: форматирование числовой оси

{
  "mark": "bar",
  "encoding": {
    "x": {"field": "category", "type": "nominal"},
    "y": {
      "field": "value",
      "type": "quantitative",
      "axis": {
        "format": ",.0f"
      }
    }
  }
}

Здесь значения оси Y отображаются с разделением тысяч и без десятичных знаков.

Форматирование в текстовых маркерах

Текстовые марки в Vega-Lite используют encoding.text.format, позволяя управлять отображением чисел внутри подписей:

{
  "mark": "text",
  "encoding": {
    "text": {
      "field": "value",
      "type": "quantitative",
      "format": ".1f"
    },
    "x": {"field": "x", "type": "ordinal"},
    "y": {"field": "y", "type": "quantitative"}
  }
}

Это особенно важно для аннотаций, где точность отображения должна быть ограничена.

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

Для временных данных format использует d3-time-format, где строки соответствуют шаблонам времени:

  • %Y — год (2026)
  • %m — месяц (01–12)
  • %d — день месяца
  • %H — часы (24-часовой формат)
  • %M — минуты
  • %S — секунды
  • %b — сокращённое название месяца
  • %B — полное название месяца

Пример форматирования даты на оси

{
  "mark": "line",
  "encoding": {
    "x": {
      "field": "date",
      "type": "temporal",
      "axis": {
        "format": "%Y-%m"
      }
    },
    "y": {
      "field": "value",
      "type": "quantitative"
    }
  }
}

Результат: подписи оси X отображаются в виде «2026-01», «2026-02» и т.д.

Отличие format от formatType

В Vega-Lite существует различие между строковым format и параметром formatType:

  • format: строковый шаблон (d3-format / d3-time-format)
  • formatType: тип интерпретации формата ("number", "time")

Пример:

{
  "field": "value",
  "type": "quantitative",
  "formatType": "number",
  "format": ".2f"
}

Явное указание formatType полезно при неоднозначных преобразованиях, особенно в сложных преобразованиях данных.

Форматирование осей через axis.format

Оси являются наиболее частым потребителем format. Vega-Lite применяет форматирование на этапе рендеринга шкалы.

Пример числовой оси с валютой:

{
  "y": {
    "field": "revenue",
    "type": "quantitative",
    "axis": {
      "format": "$,.2f"
    }
  }
}

Это позволяет отображать значения вроде:

  • $1,200.00
  • $45,000.50

Форматирование tooltip

Tooltip поддерживает независимое форматирование для каждого поля:

{
  "mark": "circle",
  "encoding": {
    "x": {"field": "x", "type": "quantitative"},
    "y": {"field": "y", "type": "quantitative"},
    "tooltip": [
      {"field": "x", "type": "quantitative", "format": ".1f"},
      {"field": "y", "type": "quantitative", "format": ".2f"}
    ]
  }
}

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

Комбинирование format с преобразованиями данных

format часто используется вместе с timeUnit и bin, но важно понимать порядок применения:

  1. преобразование данных (bin, timeUnit, aggregate)
  2. масштабирование (scale)
  3. форматирование (format)
  4. рендеринг меток

Пример с временной агрегацией:

{
  "x": {
    "field": "date",
    "type": "temporal",
    "timeUnit": "yearmonth",
    "axis": {
      "format": "%Y-%m"
    }
  }
}

Здесь timeUnit формирует новую временную гранулярность, а format отвечает за визуальное представление результата.

Локализация и форматирование

Vega-Lite не выполняет автоматическую локализацию чисел и дат, но позволяет эмулировать локализованное представление через формат:

  • десятичная запятая реализуется через post-processing (не через стандартный format)
  • разделители тысяч задаются через ,
  • валюты добавляются вручную в строку формата

Пример «европейского» формата:

{
  "field": "value",
  "type": "quantitative",
  "format": ".2f"
}

с дополнительной трансформацией в более высоком слое (например, через signal или custom format function в Vega).

Частые ошибки при использовании format

1. Применение числового формата к строковым данным

Если поле имеет тип nominal, format игнорируется.

{
  "field": "category",
  "type": "nominal",
  "format": ".2f"
}

Результат — отсутствие эффекта.


2. Несоответствие formatType типу данных

{
  "field": "date",
  "type": "temporal",
  "formatType": "number"
}

Приводит к некорректному отображению или игнорированию формата.


3. Избыточная точность

Форматы вроде .10f ухудшают читаемость визуализации и увеличивают визуальный шум.

Поведение при null и undefined

Если значение отсутствует:

  • Vega-Lite не применяет format
  • отображается пустая метка или дефолтное значение (null → пусто)
  • в tooltip может отображаться null, если не задан fallback

Рекомендуется комбинировать format с calculate или transform, если требуется подмена значений.

Влияние на производительность

format выполняется на этапе рендеринга, а не трансформации данных. Это означает:

  • минимальное влияние на pipeline данных
  • возможная нагрузка при большом количестве текстовых маркеров
  • особенно заметно в dense scatter plots с tooltip и text marks одновременно

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

Сочетание format с выражениями (labelExpr)

В Vega-Lite можно обойти format через выражения Vega:

{
  "axis": {
    "labelExpr": "datum.value.toFixed(2)"
  }
}

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

Использование в сложных визуализациях

В многослойных графиках (layer) форматирование может различаться для каждого слоя:

{
  "layer": [
    {
      "mark": "line",
      "encoding": {
        "y": {
          "field": "value",
          "type": "quantitative",
          "axis": {"format": ".1f"}
        }
      }
    },
    {
      "mark": "text",
      "encoding": {
        "text": {"field": "value", "type": "quantitative", "format": ".2f"}
      }
    }
  ]
}

Это позволяет разделять точность визуального восприятия и точность аннотаций.

Взаимодействие с scale-label formatting

Некоторые шкалы поддерживают отдельное форматирование через scale.labelExpr или axis.labelExpr, но format остаётся основным декларативным способом управления отображением.


Форматирование в Vega-Lite представляет собой слой представления, который отделяет математическое значение данных от его визуальной интерпретации, обеспечивая единообразие и контроль над отображением в различных типах визуальных элементов.