Канал shape

Канал shape в Vega-Lite используется для кодирования категориальных данных через форму графических маркеров. Он применяется преимущественно к точечным графикам и диаграммам рассеяния, где различие объектов по форме служит дополнительным визуальным измерением наряду с цветом, размером и положением.

Назначение и область применения

Канал shape предназначен для визуального различения дискретных категорий. В отличие от непрерывных шкал (например, x, y, size), он работает исключительно с категориальными или порядковыми данными.

Основная задача:

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

Использование shape ограничено mark-типами, поддерживающими символы, прежде всего point.


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

Канал shape работает только с маркерами, имеющими символическое представление:

  • point — основной тип
  • circle (как фиксированная форма, но может быть переопределена)
  • square
  • triangle
  • cross
  • diamond
  • triangle-up, triangle-down, triangle-right, triangle-left
  • stroke-варианты (в зависимости от renderer-а Vega)

При использовании shape Vega-Lite фактически выбирает символ из набора SVG-подобных примитивов Vega.


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

Канал задаётся внутри encoding объекта:

{
  "mark": "point",
  "encoding": {
    "x": { "field": "sepalLength", "type": "quantitative" },
    "y": { "field": "sepalWidth", "type": "quantitative" },
    "shape": { "field": "species", "type": "nominal" }
  }
}

Здесь species определяет форму каждой точки.


Типы данных для shape

Канал корректно работает с ограниченным набором типов:

Nominal (категориальный)

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

Пример:

"shape": {
  "field": "category",
  "type": "nominal"
}

Ordinal (порядковый)

Используется реже, так как форма плохо подходит для передачи порядка. Однако Vega-Lite может сопоставить порядок с фиксированным списком символов.

"shape": {
  "field": "rank",
  "type": "ordinal"
}

Quantitative

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


Использование фиксированных значений

Канал shape может задаваться напрямую без поля данных:

"shape": { "value": "triangle" }

Это приводит к тому, что все точки имеют одинаковую форму.


Масштабирование и легенды

Для shape применяется дискретная шкала (discrete scale), автоматически создаваемая Vega-Lite при использовании поля nominal.

Легенда

Каждому значению поля соответствует элемент легенды:

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

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

"shape": {
  "field": "group",
  "type": "nominal",
  "legend": { "title": "Группа данных" }
}

Встроенные символы Vega

Vega использует фиксированный набор символов, которые можно указать строкой:

  • "circle"
  • "square"
  • "triangle-up"
  • "triangle-down"
  • "diamond"
  • "cross"
  • "star"
  • "wedge"
  • "triangle-right"
  • "triangle-left"

Пример явного задания:

"shape": {
  "value": "diamond"
}

Сопоставление категорий и форм

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

Для контроля можно использовать scale.domain и scale.range:

"shape": {
  "field": "type",
  "type": "nominal",
  "scale": {
    "domain": ["A", "B", "C"],
    "range": ["circle", "square", "triangle"]
  }
}

Комбинация с другими каналами

Канал shape редко используется изолированно. Его эффективность возрастает при совместном использовании с другими визуальными переменными.

shape + color

"encoding": {
  "shape": { "field": "group", "type": "nominal" },
  "color": { "field": "group", "type": "nominal" }
}

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


shape + size

"encoding": {
  "shape": { "field": "type", "type": "nominal" },
  "size": { "field": "value", "type": "quantitative" }
}

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


Условное отображение shape

Vega-Lite поддерживает условное кодирование:

"shape": {
  "condition": {
    "test": "datum.value > 50",
    "value": "triangle"
  },
  "value": "circle"
}

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


Работа с трансформациями

Перед применением shape часто используются трансформации данных:

binning

"transform": [
  {
    "bin": true,
    "field": "value",
    "as": "binned"
  }
]

aggregate

"transform": [
  {
    "aggregate": [{"op": "count", "as": "count"}],
    "groupby": ["category"]
  }
]

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


Ограничения канала shape

Канал имеет ряд архитектурных ограничений:

  • не поддерживает непрерывные значения напрямую;
  • ограниченное число различимых символов;
  • зависит от SVG/Canvas renderer;
  • не подходит для плотных scatter plots с большим количеством категорий.

Поведение в Vega vs Vega-Lite

Vega-Lite

  • декларативное описание;
  • автоматическое назначение символов;
  • автоматическая легенда.

Vega

  • ручное управление symbol.type;
  • более гибкая настройка геометрии;
  • возможность кастомных path-форм.

Пример Vega (низкоуровневый):

{
  "type": "symbol",
  "encode": {
    "enter": {
      "shape": { "value": "square" }
    }
  }
}

Кастомные формы

Vega (но не Vega-Lite напрямую) позволяет использовать SVG path:

"shape": {
  "value": "M0,-1L0.6,0.8L-0.6,0.8Z"
}

В Vega-Lite это возможно только через config или post-compile изменения.


Производительность

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

  • каждый символ — отдельный SVG/Canvas draw call;
  • сложные формы увеличивают нагрузку;
  • рекомендуется ограничивать число категорий.

Оптимизационные практики:

  • уменьшение cardinality поля;
  • использование opacity вместо дополнительного shape;
  • переход к color при больших наборах данных.

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

  • применение к количественным данным без биннинга;
  • превышение числа уникальных категорий;
  • дублирование shape и color без необходимости;
  • отсутствие легенды при множестве форм;
  • использование в dense scatter без фильтрации.

Поведение при пустых или некорректных значениях

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

  • Vega-Lite назначает fallback форму;
  • может использоваться стандартный circle;
  • легенда может содержать null категорию.

Явное управление:

"shape": {
  "field": "category",
  "type": "nominal",
  "nullValue": "cross"
}

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

Канал shape сохраняется при интерактивных операциях:

  • hover (highlight);
  • selection (interval, point selection);
  • filtering.

Пример selection:

"selection": {
  "picked": { "type": "single", "fields": ["category"] }
},
"encoding": {
  "shape": {
    "field": "category",
    "type": "nominal"
  },
  "opacity": {
    "condition": { "selection": "picked", "value": 1 },
    "value": 0.3
  }
}

Свод логики применения

Канал shape эффективно работает в ситуациях, где:

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

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