bar

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

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


Базовая столбчатая диаграмма в Vega-Lite

Минимальная bar chart строится с использованием:

  • типа метки bar
  • категориальной оси x
  • числовой оси y
const 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);

Структура bar chart

Data

Источник данных:

data: {
  values: [...]
}

Вместо values часто используются:

data: {
  url: "data.json"
}

или:

data: {
  url: "data.csv"
}

Mark

Тип визуального элемента:

mark: "bar"

Полная форма:

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

Encoding

Каналы визуального кодирования:

encoding: {
  x: {...},
  y: {...}
}

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

Канал Назначение
x положение по горизонтали
y положение по вертикали
color цвет
tooltip всплывающая подсказка
order порядок
opacity прозрачность
size размер

Типы данных

В Vega-Lite тип данных обязателен.

Nominal

Категории:

type: "nominal"

Пример:

"A", "B", "C"

Quantitative

Числовые значения:

type: "quantitative"

Пример:

10, 20, 30

Ordinal

Упорядоченные категории:

type: "ordinal"

Temporal

Дата и время:

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"
    }
  }
};

Stack bar chart

Столбцы могут складываться автоматически.

encoding: {
  x: {
    field: "month",
    type: "nominal"
  },

  y: {
    aggregate: "sum",
    field: "value",
    type: "quantitative"
  },

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

Отключение stacking

y: {
  aggregate: "sum",
  field: "value",
  stack: null
}

Normalized stack

Нормализация до 100%.

y: {
  aggregate: "sum",
  field: "value",
  stack: "normalize"
}

Tooltip

Всплывающие подсказки:

encoding: {
  tooltip: [
    { field: "category", type: "nominal" },
    { field: "value", type: "quantitative" }
  ]
}

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

Hover-эффект

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"
    }
  }
};

Настройка binning

x: {
  bin: {
    maxbins: 10
  },

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

Vega-Lite и Vega

Vega-Lite

Высокоуровневое описание.

Преимущества:

  • меньше кода
  • автоматические шкалы
  • автоматическая агрегация
  • декларативность

Vega

Низкоуровневый контроль.

Позволяет:

  • вручную управлять шкалами
  • описывать сигналы
  • создавать сложную интерактивность
  • полностью контролировать rendering pipeline

Bar chart в Vega

Минимальный пример:

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"
          }
        }
      }
    }
  ]
};

Scale в Vega

Band scale

Для категорий:

type: "band"

Linear scale

Для чисел:

type: "linear"

Rect marks

Столбцы в Vega — это rect.

type: "rect"

Координаты:

Свойство Назначение
x начало
x2 конец
y верх
y2 низ

Padding

Отступы между столбцами:

padding: 0.05

Анимация и сигналы

Vega поддерживает signals:

signals: [
  {
    name: "barColor",
    value: "steelblue"
  }
]

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

fill: {
  signal: "barColor"
}

Обновление данных

view.change(
  "table",
  vega
    .changeset()
    .insert([
      { category: "D", value: 90 }
    ])
).run();

Responsive bar chart

Автоматическая адаптация:

width: "container"

Autosize

autosize: {
  type: "fit",
  contains: "padding"
}

Конфигурация

config: {
  view: {
    stroke: null
  },

  axis: {
    labelFontSize: 12,
    titleFontSize: 14
  }
}

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

Vega-Lite подходит для большинства типовых визуализаций.

При работе с очень большими объёмами данных:

  • предпочтительнее агрегация на сервере
  • следует уменьшать количество DOM-элементов
  • рекомендуется использовать Canvas renderer
  • стоит избегать чрезмерного layering

Renderer

SVG

vegaEmbed("#view", spec, {
  renderer: "svg"
});

Преимущества:

  • чёткое масштабирование
  • удобная отладка

Недостатки:

  • хуже производительность

Canvas

vegaEmbed("#view", spec, {
  renderer: "canvas"
});

Преимущества:

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

Встраивание Vega-Lite

Подключение через CDN

<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);

Частые ошибки

Отсутствует type

Неверно:

x: {
  field: "category"
}

Верно:

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

Неверный тип данных

type: "quantitative"

для строковых категорий приводит к ошибкам шкалы.


Некорректный stack

Stack работает только для агрегированных значений.


Перепутанные оси

Для вертикального bar chart:

  • x — категории
  • y — числа

Практические сценарии использования

Столбчатые диаграммы особенно эффективны для:

  • сравнения продаж
  • анализа категорий
  • отображения рейтингов
  • распределения частот
  • анализа KPI
  • сравнения групп
  • построения dashboard
  • отображения статистики по времени

Сравнение bar и line chart

Тип Использование
Bar chart сравнение категорий
Line chart изменение во времени
Histogram распределение
Area chart накопленные значения

Рекомендации по визуальному дизайну

Не перегружать цветами

Избыточное количество цветов ухудшает читаемость.


Сортировать категории

Сортировка улучшает восприятие.


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

Большое количество labels создаёт визуальный шум.


Ограничивать количество категорий

Оптимально:

  • 5–15 столбцов
  • короткие названия
  • читаемые подписи

Основные свойства bar mark

Свойство Назначение
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
}

Комбинация bar и line

Layering позволяет совмещать графики.

layer: [
  {
    mark: "bar"
  },

  {
    mark: "line"
  }
]

Faceting

Разделение диаграмм по категориям.

facet: {
  field: "region",
  type: "nominal"
}

Repeat

Повторение визуализации:

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

Transform

Преобразование данных внутри спецификации.

Filter

transform: [
  {
    filter: "datum.value > 10"
  }
]

Calculate

transform: [
  {
    calculate: "datum.price * datum.count",
    as: "total"
  }
]

Aggregate

transform: [
  {
    aggregate: [
      {
        op: "sum",
        field: "sales",
        as: "total_sales"
      }
    ],

    groupby: ["category"]
  }
]

Архитектура Vega-Lite

Pipeline визуализации:

  1. Data
  2. Transform
  3. Scale
  4. Encode
  5. Render

Каждый этап декларативно описывается в JSON-спецификации.


JSON-ориентированный подход

Vega/Vega-Lite используют сериализуемые спецификации.

Преимущества:

  • хранение конфигураций
  • генерация графиков на сервере
  • интеграция с API
  • переносимость
  • воспроизводимость визуализаций

Экосистема Vega

Vega

Низкоуровневый движок визуализации.


Vega-Lite

Высокоуровневый декларативный слой.


Vega-Embed

Интеграция графиков в браузер.


Vega Tooltip

Расширение для tooltip.


Типичный workflow

  1. Подготовка данных
  2. Создание спецификации
  3. Настройка encoding
  4. Добавление transforms
  5. Настройка интерактивности
  6. Рендеринг через vegaEmbed
  7. Обновление данных через API Vega