Оценка плотности распределения (Density Estimation) используется для анализа формы распределения числовых данных. В отличие от гистограммы, где значения группируются по интервалам, оценка плотности строит непрерывную сглаженную кривую, отражающую вероятность появления значений в различных областях диапазона.
В Vega-Lite для этого применяется трансформация density,
основанная на методе KDE (Kernel Density Estimation — ядерная оценка
плотности).
Трансформация density позволяет:
Чаще всего density используется:
Алгоритм KDE строит непрерывную функцию плотности вероятности на основе исходных наблюдений.
Каждое значение добавляет вклад в итоговую кривую через ядро сглаживания.
Основные особенности:
Минимальная конфигурация:
{
"transform": [
{
"density": "value"
}
]
}
Где:
density — поле с числовыми значениями;<!DOCTYPE html>
<html>
<head>
<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>
</head>
<body>
<div id="view"></div>
<script>
const spec = {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{"score": 10},
{"score": 12},
{"score": 15},
{"score": 16},
{"score": 18},
{"score": 20},
{"score": 21},
{"score": 25},
{"score": 27},
{"score": 30}
]
},
"transform": [
{
"density": "score"
}
],
"mark": "line",
"encoding": {
"x": {
"field": "value",
"type": "quantitative"
},
"y": {
"field": "density",
"type": "quantitative"
}
}
};
vegaEmbed('#view', spec);
</script>
</body>
</html>
После выполнения трансформации Vega-Lite создаёт новые данные:
[
{ "value": 10, "density": 0.01 },
{ "value": 11, "density": 0.03 },
{ "value": 12, "density": 0.05 }
]
Где:
value — координата по оси X;density — оценка плотности.Эти значения затем используются для построения линии.
По умолчанию создаются:
| Поле | Назначение |
|---|---|
value |
значение по оси X |
density |
вычисленная плотность |
Названия можно изменить через параметр as.
{
"density": "score",
"as": ["x", "kde"]
}
Теперь результат:
{
"x": 15,
"kde": 0.08
}
Использование:
"encoding": {
"x": {"field": "x"},
"y": {"field": "kde"}
}
Параметр extent определяет диапазон вычисления
плотности.
{
"density": "score",
"extent": [0, 100]
}
Без extent Vega-Lite автоматически определяет диапазон
на основе данных.
extent полезен:
steps определяет количество вычисляемых точек.
{
"density": "score",
"steps": 200
}
Малое значение:
"steps": 20
Большое значение:
"steps": 500
bandwidth задаёт степень сглаживания.
Это один из важнейших параметров KDE.
{
"density": "score",
"bandwidth": 1
}
Особенности:
{
"density": "score",
"bandwidth": 20
}
Особенности:
{
"density": "score",
"bandwidth": 2
}
{
"density": "score",
"bandwidth": 15
}
Если параметр не указан:
{
"density": "score"
}
Vega-Lite автоматически вычисляет подходящее значение.
В большинстве случаев этого достаточно.
По умолчанию плотность нормализуется.
Площадь под кривой равна 1.
{
"density": "score"
}
{
"density": "score",
"counts": true
}
Теперь:
Одна из самых мощных возможностей — вычисление KDE отдельно для групп.
Используется параметр groupby.
<!DOCTYPE html>
<html>
<head>
<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>
</head>
<body>
<div id="view"></div>
<script>
const spec = {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{"group": "A", "score": 10},
{"group": "A", "score": 15},
{"group": "A", "score": 20},
{"group": "B", "score": 30},
{"group": "B", "score": 35},
{"group": "B", "score": 40}
]
},
"transform": [
{
"density": "score",
"groupby": ["group"]
}
],
"mark": "line",
"encoding": {
"x": {
"field": "value",
"type": "quantitative"
},
"y": {
"field": "density",
"type": "quantitative"
},
"color": {
"field": "group",
"type": "nominal"
}
}
};
vegaEmbed('#view', spec);
</script>
</body>
</html>
Для каждой группы:
Очень популярный вариант — использование area.
{
"mark": "area"
}
Полный пример:
{
"transform": [
{
"density": "score"
}
],
"mark": {
"type": "area",
"opacity": 0.5
}
}
Часто KDE комбинируется с гистограммой.
{
"layer": [
{
"mark": "bar"
},
{
"mark": "line"
}
]
}
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"url": "data/movies.json"
},
"layer": [
{
"mark": {
"type": "bar",
"opacity": 0.4
},
"encoding": {
"x": {
"bin": true,
"field": "IMDB_Rating",
"type": "quantitative"
},
"y": {
"aggregate": "count"
}
}
},
{
"transform": [
{
"density": "IMDB_Rating",
"counts": true
}
],
"mark": {
"type": "line",
"color": "red"
},
"encoding": {
"x": {
"field": "value",
"type": "quantitative"
},
"y": {
"field": "density",
"type": "quantitative"
}
}
}
]
}
KDE хорошо сочетается с параметрами (params) и
фильтрами.
{
"params": [
{
"name": "minScore",
"value": 10,
"bind": {
"input": "range",
"min": 0,
"max": 100
}
}
]
}
{
"transform": [
{
"filter": "datum.score >= minScore"
},
{
"density": "score"
}
]
}
KDE удобно комбинировать с facet.
{
"facet": {
"field": "category",
"type": "nominal"
},
"spec": {
"transform": [
{
"density": "score"
}
],
"mark": "line"
}
}
Параметр cumulative строит накопленное
распределение.
{
"density": "score",
"cumulative": true
}
Значение отражает вероятность того, что случайная величина:
X <= x
Это аналог функции распределения CDF.
| Характеристика | Histogram | Density |
|---|---|---|
| Основа | интервалы | непрерывная функция |
| Сглаживание | нет | есть |
| Детализация | средняя | высокая |
| Шум | ниже | выше |
| Визуальная плавность | низкая | высокая |
| Density | Boxplot |
|---|---|
| показывает форму распределения | показывает статистические сводки |
| отображает пики | показывает квартили |
| полезна для анализа структуры | полезен для быстрого сравнения |
KDE требует дополнительных вычислений.
На производительность влияют:
steps;bandwidth;{
"steps": 50
}
{
"extent": [0, 100]
}
Иногда KDE лучше вычислять на сервере.
Особенно:
{
"mark": {
"type": "line",
"strokeWidth": 3,
"color": "steelblue"
}
}
{
"mark": {
"type": "line",
"interpolate": "monotone"
}
}
| Тип | Описание |
|---|---|
linear |
прямые сегменты |
monotone |
плавная линия |
basis |
spline-интерполяция |
step |
ступенчатая линия |
Хотя KDE обычно применяется к количественным данным, она может использоваться и для временных значений.
{
"density": "timestamp"
}
Однако чаще временные данные:
В чистом Vega трансформация выглядит так:
{
"type": "density",
"field": "score"
}
Vega-Lite автоматически преобразует декларативное описание в соответствующую Vega-структуру.
<!DOCTYPE html>
<html>
<head>
<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>
</head>
<body>
<div id="view"></div>
<script>
const spec = {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"width": 700,
"height": 400,
"data": {
"url": "data/movies.json"
},
"transform": [
{
"filter": "datum.IMDB_Rating != null"
},
{
"density": "IMDB_Rating",
"bandwidth": 0.3,
"steps": 300,
"extent": [0, 10]
}
],
"mark": {
"type": "area",
"interpolate": "monotone",
"opacity": 0.6,
"line": true
},
"encoding": {
"x": {
"field": "value",
"type": "quantitative",
"title": "IMDB Rating"
},
"y": {
"field": "density",
"type": "quantitative",
"title": "Density"
},
"tooltip": [
{"field": "value"},
{"field": "density"}
]
}
};
vegaEmbed('#view', spec);
</script>
</body>
</html>
Неправильно:
{
"density": "country"
}
density требует числовое поле.
{
"bandwidth": 0.01
}
Результат:
{
"bandwidth": 100
}
Проблемы:
{
"steps": 5000
}
Последствия:
{
"density": "rating"
}
{
"density": "salary"
}
{
"density": "responseTime"
}
KDE активно используется для:
{
"transform": [
{
"filter": "datum.score > 50"
},
{
"density": "score"
}
]
}
{
"transform": [
{
"calculate": "datum.price * datum.count",
"as": "total"
},
{
"density": "total"
}
]
}
{
"transform": [
{
"window": [
{
"op": "rank",
"as": "rank"
}
]
},
{
"density": "rank"
}
]
}
При использовании density Vega-Lite:
Исходные данные при этом не изменяются.
density относится к transform-операциям.
Следовательно:
Чаще всего используются:
| Mark | Назначение |
|---|---|
line |
классическая KDE |
area |
заполненная плотность |
trail |
переменная толщина |
point |
отображение sampled points |
Важно понимать:
Поэтому density следует интерпретировать как инструмент визуального анализа, а не как строгую математическую модель.