filter: фильтрация строк

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


transform: filter как базовый механизм

В Vega-Lite основной способ фильтрации — использование трансформации filter. Она применяется к набору данных до построения визуальных каналов.

{
  "data": {
    "values": [
      {"category": "A", "value": 10},
      {"category": "B", "value": 25},
      {"category": "A", "value": 7}
    ]
  },
  "transform": [
    {
      "filter": "datum.value > 10"
    }
  ],
  "mark": "bar",
  "encoding": {
    "x": {"field": "category", "type": "nominal"},
    "y": {"field": "value", "type": "quantitative"}
  }
}

В этом примере каждая строка проходит через предикат datum.value > 10. Только записи, удовлетворяющие условию, попадают в дальнейший pipeline.


Язык выражений фильтрации

Фильтры используют выражения, основанные на синтаксисе Vega Expression Language. Доступ к полям осуществляется через datum.

Основные операторы

Логические операции:

  • && — логическое И
  • || — логическое ИЛИ
  • ! — отрицание
{
  "filter": "datum.value > 10 && datum.category === 'A'"
}

Сравнения:

  • ==, !=
  • >, <, >=, <=

Работа с типами

Фильтрация чувствительна к типам данных. Строковые сравнения выполняются строго:

{
  "filter": "datum.status == 'active'"
}

Использование функций в фильтрах

Expression language поддерживает набор встроенных функций.

Проверка строк

{
  "filter": "indexof(datum.name, 'test') >= 0"
}

Работа с массивами

{
  "filter": "includes(['A', 'B', 'C'], datum.category)"
}

Проверка диапазонов

{
  "filter": "datum.value >= 10 && datum.value <= 50"
}

Фильтрация через параметры (params)

В Vega-Lite динамическая фильтрация часто реализуется через параметры, позволяющие связывать UI-состояние с данными.

Скалярный параметр

{
  "params": [
    {
      "name": "threshold",
      "value": 10
    }
  ],
  "transform": [
    {
      "filter": "datum.value > threshold"
    }
  ]
}

Значение threshold становится сигналом, используемым в выражении фильтра.


Фильтрация через selection

Selection-параметры позволяют строить интерактивные фильтры на основе выделения.

interval selection (brush)

{
  "params": [
    {
      "name": "brush",
      "select": "interval"
    }
  ],
  "transform": [
    {
      "filter": "brush.x && datum.value >= brush.x[0] && datum.value <= brush.x[1]"
    }
  ]
}

Здесь фильтрация зависит от диапазона, выбранного пользователем.


point selection

{
  "params": [
    {
      "name": "picked",
      "select": "point"
    }
  ],
  "transform": [
    {
      "filter": "picked.category ? datum.category === picked.category : true"
    }
  ]
}

Если элемент выбран, отображаются только соответствующие строки.


Vega (низкоуровневая модель)

В Vega фильтрация реализуется через трансформацию filter внутри data.transform.

{
  "data": [
    {
      "name": "table",
      "values": [
        {"x": 1},
        {"x": 2},
        {"x": 3}
      ],
      "transform": [
        {
          "type": "filter",
          "expr": "datum.x > 1"
        }
      ]
    }
  ]
}

Здесь используется поле expr, но семантика идентична Vega-Lite.


Комбинирование нескольких фильтров

Фильтры можно цеплять последовательно, формируя pipeline предикатов.

{
  "transform": [
    {
      "filter": "datum.value > 0"
    },
    {
      "filter": "datum.category != 'C'"
    }
  ]
}

Каждый этап уменьшает множество данных, и порядок может влиять на производительность.


Условная фильтрация через if-подобные конструкции

Expression language поддерживает тернарный оператор:

{
  "filter": "datum.type === 'A' ? datum.value > 10 : datum.value > 20"
}

Такие выражения позволяют реализовывать ветвления внутри одного предиката без дополнительной трансформации.


Фильтрация с учётом null и undefined

Отсутствующие значения требуют явной обработки:

{
  "filter": "datum.value != null && datum.value > 5"
}

Без проверки на null возможны некорректные результаты или исключение в выражении.


Регулярные выражения в фильтрах

Поддерживаются regex-операции через test:

{
  "filter": "test(datum.name, /^A/)"
}

Фильтрация выполняется по совпадению строки с шаблоном.


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

Фильтрация выполняется до вычисления шкал и отрисовки, поэтому влияет на весь pipeline визуализации.

Ключевые особенности:

  • ранняя фильтрация уменьшает нагрузку на scales и marks
  • сложные выражения в filter могут стать узким местом
  • selection-based фильтры добавляют реактивность, но увеличивают количество сигналов

Оптимизация часто сводится к минимизации вычислений внутри expression language и предварительной агрегации данных.


Фильтрация и агрегации

Фильтрация может выполняться до или после агрегации, в зависимости от порядка трансформаций.

До агрегации

{
  "transform": [
    {
      "filter": "datum.value > 0"
    },
    {
      "aggregate": [
        {"op": "sum", "field": "value", "as": "total"}
      ],
      "groupby": ["category"]
    }
  ]
}

После агрегации

{
  "transform": [
    {
      "aggregate": [
        {"op": "sum", "field": "value", "as": "total"}
      ],
      "groupby": ["category"]
    },
    {
      "filter": "datum.total > 100"
    }
  ]
}

Порядок трансформаций меняет смысл результата.


Фильтрация по вычисляемым полям

Часто фильтрация основывается на выражениях, создаваемых через calculate.

{
  "transform": [
    {
      "calculate": "datum.value * 2",
      "as": "scaled"
    },
    {
      "filter": "datum.scaled > 50"
    }
  ]
}

Типовые паттерны фильтрации

Категориальный фильтр

{
  "filter": "datum.category === 'B'"
}

Диапазон значений

{
  "filter": "datum.value >= 10 && datum.value <= 100"
}

Множественный выбор

{
  "filter": "includes(['A','C'], datum.category)"
}

Фильтр по состоянию параметра

{
  "filter": "!selected || datum.category === selected.category"
}

Роль фильтрации в интерактивных визуализациях

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

Фильтрация в этом контексте не является отдельной операцией, а становится частью реактивного графа зависимостей, где любое изменение сигнала приводит к пересчёту данных и перерисовке соответствующих mark-слоёв.