circle и square

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

В основе обоих примитивов лежит концепция точечного отображения данных. Различие заключается исключительно в форме:

  • circle — окружность;
  • square — квадрат.

Оба marks часто применяются:

  • в scatter plot;
  • bubble chart;
  • heatmap;
  • dot plot;
  • network graph;
  • интерактивных dashboard;
  • визуализации кластеров;
  • отображении географических точек.

circle в Vega-Lite

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

Минимальная спецификация:

{
  "mark": "circle"
}

Полноценный пример:

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",

  "data": {
    "values": [
      {"x": 10, "y": 28},
      {"x": 20, "y": 55},
      {"x": 30, "y": 43},
      {"x": 40, "y": 91}
    ]
  },

  "mark": "circle",

  "encoding": {
    "x": {"field": "x", "type": "quantitative"},
    "y": {"field": "y", "type": "quantitative"}
  }
}

Размер окружностей

Размер задаётся через свойство size.

Фиксированный размер

{
  "mark": {
    "type": "circle",
    "size": 300
  }
}

Размер задаётся в квадратных пикселях, а не в радиусе.


Размер через данные

{
  "encoding": {
    "size": {
      "field": "population",
      "type": "quantitative"
    }
  }
}

В таком случае формируется bubble chart.


Цвет окружностей

Статический цвет

{
  "mark": {
    "type": "circle",
    "color": "steelblue"
  }
}

Цвет через поле

{
  "encoding": {
    "color": {
      "field": "category",
      "type": "nominal"
    }
  }
}

Прозрачность

Свойство opacity особенно важно при большом количестве точек.

{
  "mark": {
    "type": "circle",
    "opacity": 0.4
  }
}

Полезно для борьбы с overplotting.


Границы окружностей

Stroke

{
  "mark": {
    "type": "circle",
    "stroke": "black",
    "strokeWidth": 2
  }
}

Scatter Plot на основе circle

Классический scatter plot

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",

  "data": {
    "url": "data/cars.json"
  },

  "mark": "circle",

  "encoding": {
    "x": {
      "field": "Horsepower",
      "type": "quantitative"
    },

    "y": {
      "field": "Miles_per_Gallon",
      "type": "quantitative"
    },

    "color": {
      "field": "Origin",
      "type": "nominal"
    }
  }
}

Bubble Chart

circle особенно хорошо подходит для bubble chart.

{
  "mark": "circle",

  "encoding": {
    "x": {"field": "income", "type": "quantitative"},
    "y": {"field": "life_expectancy", "type": "quantitative"},

    "size": {
      "field": "population",
      "type": "quantitative"
    },

    "color": {
      "field": "continent",
      "type": "nominal"
    }
  }
}

Интерактивность

Hover-эффекты

{
  "selection": {
    "highlight": {
      "type": "single",
      "on": "mouseover",
      "empty": "none"
    }
  },

  "mark": "circle",

  "encoding": {
    "opacity": {
      "condition": {
        "selection": "highlight",
        "value": 1
      },
      "value": 0.3
    }
  }
}

Tooltip

{
  "encoding": {
    "tooltip": [
      {"field": "name"},
      {"field": "value"}
    ]
  }
}

square в Vega-Lite

Базовое использование

{
  "mark": "square"
}

Отличия square от circle

Свойство circle square
Форма Круг Квадрат
Восприятие плотности Мягкое Более структурированное
Heatmap Реже Очень часто
Pixel-style визуализация Нет Да
Табличные данные Умеренно Отлично
Геометрическая строгость Ниже Выше

Размер квадратов

{
  "mark": {
    "type": "square",
    "size": 400
  }
}

Heatmap на square

Одно из главных применений.

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",

  "data": {
    "values": [
      {"x": 1, "y": 1, "value": 10},
      {"x": 2, "y": 1, "value": 30},
      {"x": 1, "y": 2, "value": 50},
      {"x": 2, "y": 2, "value": 90}
    ]
  },

  "mark": "square",

  "encoding": {
    "x": {"field": "x", "type": "ordinal"},
    "y": {"field": "y", "type": "ordinal"},

    "color": {
      "field": "value",
      "type": "quantitative"
    }
  }
}

Pixel Visualization

square подходит для визуализации матриц и пиксельных структур.

{
  "mark": {
    "type": "square",
    "size": 100
  }
}

Настройка формы через конфигурацию

Глобальная настройка

{
  "config": {
    "circle": {
      "opacity": 0.7,
      "color": "tomato"
    }
  }
}

Настройка square

{
  "config": {
    "square": {
      "filled": true,
      "stroke": "black"
    }
  }
}

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

В низкоуровневом Vega синтаксис отличается.


Circle в Vega

Базовый пример

{
  "marks": [
    {
      "type": "symbol",

      "encode": {
        "enter": {
          "x": {"value": 100},
          "y": {"value": 100},
          "size": {"value": 400},
          "shape": {"value": "circle"},
          "fill": {"value": "steelblue"}
        }
      }
    }
  ]
}

Square в Vega

{
  "marks": [
    {
      "type": "symbol",

      "encode": {
        "enter": {
          "x": {"value": 150},
          "y": {"value": 150},
          "shape": {"value": "square"},
          "size": {"value": 600},
          "fill": {"value": "orange"}
        }
      }
    }
  ]
}

Shape как универсальный механизм

В Vega используется mark symbol, а форма задаётся через shape.

Поддерживаемые значения:

  • circle
  • square
  • cross
  • diamond
  • triangle-up
  • triangle-down
  • triangle-right
  • triangle-left

Динамическая форма

{
  "encode": {
    "update": {
      "shape": {
        "field": "shapeType"
      }
    }
  }
}

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

Scale для size

{
  "encoding": {
    "size": {
      "field": "amount",
      "type": "quantitative",
      "scale": {
        "range": [10, 1000]
      }
    }
  }
}

Легенда размеров

{
  "encoding": {
    "size": {
      "field": "population",
      "legend": {
        "title": "Population"
      }
    }
  }
}

Наложение marks

circle и square часто используются вместе.

Layer

{
  "layer": [
    {
      "mark": "square"
    },

    {
      "mark": {
        "type": "circle",
        "color": "white",
        "size": 100
      }
    }
  ]
}

Условное форматирование

{
  "encoding": {
    "color": {
      "condition": {
        "test": "datum.value > 50",
        "value": "red"
      },
      "value": "green"
    }
  }
}

Анимация через сигналы Vega

{
  "signals": [
    {
      "name": "hover",
      "value": null,
      "on": [
        {
          "events": "symbol:mouseover",
          "update": "datum"
        },

        {
          "events": "symbol:mouseout",
          "update": "null"
        }
      ]
    }
  ]
}

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

Когда использовать circle

Подходит для:

  • scatter plot;
  • bubble chart;
  • network graph;
  • интерактивных точек;
  • отображения координат.

Когда использовать square

Подходит для:

  • heatmap;
  • matrix chart;
  • grid visualization;
  • pixel visualization;
  • календарных графиков;
  • плотных дискретных сеток.

Оптимизация больших наборов данных

При отображении тысяч объектов полезны:

{
  "mark": {
    "type": "circle",
    "opacity": 0.2
  }
}

Уменьшение размера

{
  "mark": {
    "type": "square",
    "size": 20
  }
}

Filled и hollow symbols

Полая окружность

{
  "mark": {
    "type": "circle",
    "filled": false,
    "stroke": "black"
  }
}

Полый квадрат

{
  "mark": {
    "type": "square",
    "filled": false,
    "strokeWidth": 2
  }
}

Комбинация с transform

Aggregation

{
  "transform": [
    {
      "aggregate": [
        {
          "op": "mean",
          "field": "value",
          "as": "avg_value"
        }
      ],

      "groupby": ["category"]
    }
  ]
}

Jitter для борьбы с наложением

{
  "transform": [
    {
      "calculate": "datum.x + random() * 0.5",
      "as": "jx"
    }
  ]
}

Density Plot через circle

{
  "mark": {
    "type": "circle",
    "opacity": 0.1
  }
}

Square как элемент сетки

{
  "encoding": {
    "x": {"field": "col"},
    "y": {"field": "row"}
  }
}

Размеры и восприятие

Важно учитывать визуальную интерпретацию:

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

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

circle обычно применяется:

  • в scatter chart;
  • KPI-point;
  • live metrics;
  • geo points.

square используется:

  • в heatmap;
  • status matrix;
  • monitoring grid;
  • activity map.

Стилизация через theme

{
  "config": {
    "style": {
      "cell": {
        "stroke": "transparent"
      }
    }
  }
}

Типичные ошибки

Слишком большие размеры

{
  "size": 10000
}

Может приводить к перекрытию визуализации.


Отсутствие прозрачности

При большом количестве точек:

{
  "opacity": 1
}

делает график нечитаемым.


Неверный тип шкалы

{
  "type": "nominal"
}

для непрерывных значений ухудшает визуальное восприятие.


Практический пример: bubble heatmap

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",

  "data": {
    "values": [
      {"x": "A", "y": "Q1", "v": 28},
      {"x": "B", "y": "Q1", "v": 55},
      {"x": "A", "y": "Q2", "v": 43},
      {"x": "B", "y": "Q2", "v": 91}
    ]
  },

  "layer": [
    {
      "mark": "square",

      "encoding": {
        "x": {"field": "x", "type": "ordinal"},
        "y": {"field": "y", "type": "ordinal"},

        "color": {
          "field": "v",
          "type": "quantitative"
        }
      }
    },

    {
      "mark": {
        "type": "circle",
        "color": "white"
      },

      "encoding": {
        "x": {"field": "x", "type": "ordinal"},
        "y": {"field": "y", "type": "ordinal"},

        "size": {
          "field": "v",
          "type": "quantitative"
        }
      }
    }
  ]
}