Столбчатые диаграммы — один из базовых способов визуализации категориальных данных. В экосистеме JavaScript-библиотек Vega и Vega-Lite они используются для отображения сравнений между группами, анализа распределений, построения гистограмм и визуального анализа агрегированных значений.
В Vega-Lite создание bar chart сводится к декларативному описанию данных и каналов кодирования, тогда как Vega предоставляет низкоуровневый контроль над каждым элементом визуализации.
Минимальная bar chart строится с использованием:
barxyconst spec = {
data: {
values: [
{ category: "A", value: 28 },
{ category: "B", value: 55 },
{ category: "C", value: 43 },
{ category: "D", value: 91 }
]
},
mark: "bar",
encoding: {
x: {
field: "category",
type: "nominal"
},
y: {
field: "value",
type: "quantitative"
}
}
};
vegaEmbed("#view", spec);
Источник данных:
data: {
values: [...]
}
Вместо values часто используются:
data: {
url: "data.json"
}
или:
data: {
url: "data.csv"
}
Тип визуального элемента:
mark: "bar"
Полная форма:
mark: {
type: "bar",
color: "steelblue"
}
Каналы визуального кодирования:
encoding: {
x: {...},
y: {...}
}
Наиболее распространённые каналы:
| Канал | Назначение |
|---|---|
| x | положение по горизонтали |
| y | положение по вертикали |
| color | цвет |
| tooltip | всплывающая подсказка |
| order | порядок |
| opacity | прозрачность |
| size | размер |
В Vega-Lite тип данных обязателен.
Категории:
type: "nominal"
Пример:
"A", "B", "C"
Числовые значения:
type: "quantitative"
Пример:
10, 20, 30
Упорядоченные категории:
type: "ordinal"
Дата и время:
type: "temporal"
Для горизонтальной диаграммы оси меняются местами.
const spec = {
data: {
values: [
{ country: "USA", population: 331 },
{ country: "India", population: 1391 },
{ country: "China", population: 1444 }
]
},
mark: "bar",
encoding: {
y: {
field: "country",
type: "nominal"
},
x: {
field: "population",
type: "quantitative"
}
}
};
mark: {
type: "bar",
color: "#4C78A8"
}
encoding: {
color: {
field: "category",
type: "nominal"
}
}
encoding: {
color: {
field: "category",
type: "nominal",
scale: {
range: ["#ff6b6b", "#4ecdc4", "#ffe66d"]
}
}
}
Используется слой (layer).
const spec = {
data: {
values: [
{ category: "A", value: 10 },
{ category: "B", value: 25 },
{ category: "C", value: 40 }
]
},
layer: [
{
mark: "bar",
encoding: {
x: {
field: "category",
type: "nominal"
},
y: {
field: "value",
type: "quantitative"
}
}
},
{
mark: {
type: "text",
dy: -5
},
encoding: {
x: {
field: "category",
type: "nominal"
},
y: {
field: "value",
type: "quantitative"
},
text: {
field: "value",
type: "quantitative"
}
}
}
]
};
По умолчанию:
x: {
field: "category",
type: "nominal"
}
x: {
field: "category",
type: "nominal",
sort: "-y"
}
sort: ["High", "Medium", "Low"]
width: 500
mark: {
type: "bar",
size: 40
}
config: {
bar: {
discreteBandSize: 30
}
}
Vega-Lite автоматически агрегирует данные.
y: {
aggregate: "sum",
field: "sales",
type: "quantitative"
}
aggregate: "mean"
aggregate: "count"
aggregate: "max"
Используется дополнительное поле color.
const spec = {
data: {
values: [
{ month: "Jan", type: "A", value: 30 },
{ month: "Jan", type: "B", value: 20 },
{ month: "Feb", type: "A", value: 50 },
{ month: "Feb", type: "B", value: 35 }
]
},
mark: "bar",
encoding: {
x: {
field: "month",
type: "nominal"
},
y: {
field: "value",
type: "quantitative"
},
color: {
field: "type",
type: "nominal"
},
xOffset: {
field: "type"
}
}
};
Столбцы могут складываться автоматически.
encoding: {
x: {
field: "month",
type: "nominal"
},
y: {
aggregate: "sum",
field: "value",
type: "quantitative"
},
color: {
field: "category",
type: "nominal"
}
}
y: {
aggregate: "sum",
field: "value",
stack: null
}
Нормализация до 100%.
y: {
aggregate: "sum",
field: "value",
stack: "normalize"
}
Всплывающие подсказки:
encoding: {
tooltip: [
{ field: "category", type: "nominal" },
{ field: "value", type: "quantitative" }
]
}
mark: {
type: "bar",
tooltip: true
}
const spec = {
params: [
{
name: "hover",
select: {
type: "point",
on: "mouseover"
}
}
],
mark: "bar",
encoding: {
opacity: {
condition: {
param: "hover",
value: 1
},
value: 0.5
}
}
};
Используется по умолчанию.
y: {
field: "value",
type: "quantitative",
scale: {
type: "log"
}
}
x: {
title: "Категория"
}
y: {
axis: {
format: ".2f"
}
}
x: {
axis: {
labelAngle: -45
}
}
y: {
axis: {
grid: true
}
}
encoding: {
color: {
condition: {
test: "datum.value > 50",
value: "red"
},
value: "steelblue"
}
}
Histogram строится через binning.
const spec = {
data: {
values: [
{ value: 1 },
{ value: 2 },
{ value: 2 },
{ value: 3 },
{ value: 4 },
{ value: 5 }
]
},
mark: "bar",
encoding: {
x: {
bin: true,
field: "value",
type: "quantitative"
},
y: {
aggregate: "count",
type: "quantitative"
}
}
};
x: {
bin: {
maxbins: 10
},
field: "value",
type: "quantitative"
}
Высокоуровневое описание.
Преимущества:
Низкоуровневый контроль.
Позволяет:
Минимальный пример:
const spec = {
$schema: "https://vega.github.io/schema/vega/v5.json",
width: 400,
height: 200,
padding: 5,
data: [
{
name: "table",
values: [
{ category: "A", value: 28 },
{ category: "B", value: 55 },
{ category: "C", value: 43 }
]
}
],
scales: [
{
name: "xscale",
type: "band",
domain: {
data: "table",
field: "category"
},
range: "width",
padding: 0.05
},
{
name: "yscale",
domain: {
data: "table",
field: "value"
},
nice: true,
range: "height"
}
],
axes: [
{
orient: "bottom",
scale: "xscale"
},
{
orient: "left",
scale: "yscale"
}
],
marks: [
{
type: "rect",
from: {
data: "table"
},
encode: {
enter: {
x: {
scale: "xscale",
field: "category"
},
width: {
scale: "xscale",
band: 1
},
y: {
scale: "yscale",
field: "value"
},
y2: {
scale: "yscale",
value: 0
}
},
update: {
fill: {
value: "steelblue"
}
}
}
}
]
};
Для категорий:
type: "band"
Для чисел:
type: "linear"
Столбцы в Vega — это rect.
type: "rect"
Координаты:
| Свойство | Назначение |
|---|---|
| x | начало |
| x2 | конец |
| y | верх |
| y2 | низ |
Отступы между столбцами:
padding: 0.05
Vega поддерживает signals:
signals: [
{
name: "barColor",
value: "steelblue"
}
]
Использование:
fill: {
signal: "barColor"
}
view.change(
"table",
vega
.changeset()
.insert([
{ category: "D", value: 90 }
])
).run();
Автоматическая адаптация:
width: "container"
autosize: {
type: "fit",
contains: "padding"
}
config: {
view: {
stroke: null
},
axis: {
labelFontSize: 12,
titleFontSize: 14
}
}
Vega-Lite подходит для большинства типовых визуализаций.
При работе с очень большими объёмами данных:
vegaEmbed("#view", spec, {
renderer: "svg"
});
Преимущества:
Недостатки:
vegaEmbed("#view", spec, {
renderer: "canvas"
});
Преимущества:
<script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-lite@5"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
<div id="view"></div>
vegaEmbed("#view", spec);
Неверно:
x: {
field: "category"
}
Верно:
x: {
field: "category",
type: "nominal"
}
type: "quantitative"
для строковых категорий приводит к ошибкам шкалы.
Stack работает только для агрегированных значений.
Для вертикального bar chart:
x — категорииy — числаСтолбчатые диаграммы особенно эффективны для:
| Тип | Использование |
|---|---|
| Bar chart | сравнение категорий |
| Line chart | изменение во времени |
| Histogram | распределение |
| Area chart | накопленные значения |
Избыточное количество цветов ухудшает читаемость.
Сортировка улучшает восприятие.
Большое количество labels создаёт визуальный шум.
Оптимально:
| Свойство | Назначение |
|---|---|
| color | цвет |
| size | ширина |
| opacity | прозрачность |
| tooltip | подсказка |
| cornerRadius | скругление |
| stroke | граница |
mark: {
type: "bar",
cornerRadiusTopLeft: 4,
cornerRadiusTopRight: 4
}
mark: {
type: "bar",
stroke: "black",
strokeWidth: 1
}
mark: {
type: "bar",
opacity: 0.7
}
Layering позволяет совмещать графики.
layer: [
{
mark: "bar"
},
{
mark: "line"
}
]
Разделение диаграмм по категориям.
facet: {
field: "region",
type: "nominal"
}
Повторение визуализации:
repeat: {
column: ["sales", "profit"]
}
Преобразование данных внутри спецификации.
transform: [
{
filter: "datum.value > 10"
}
]
transform: [
{
calculate: "datum.price * datum.count",
as: "total"
}
]
transform: [
{
aggregate: [
{
op: "sum",
field: "sales",
as: "total_sales"
}
],
groupby: ["category"]
}
]
Pipeline визуализации:
Каждый этап декларативно описывается в JSON-спецификации.
Vega/Vega-Lite используют сериализуемые спецификации.
Преимущества:
Низкоуровневый движок визуализации.
Высокоуровневый декларативный слой.
Интеграция графиков в браузер.
Расширение для tooltip.
vegaEmbed