Перейти к основному содержимому

Улучшите качество данных с помощью групповых проверок

· 7 мин. чтения
Emily Riederer

Представьте, что вы отвечаете за мониторинг безопасности системы метро. С чего бы вы начали? Скорее всего, вы начнете с размышлений о ключевых рисках, таких как столкновение или сход с рельсов, подумаете о причинных факторах, таких как программное обеспечение для планирования и состояние путей, которые могут привести к плохим результатам, и установите процессы и метрики для обнаружения таких ситуаций. Вы бы не стали слепо применять нерелевантные отраслевые стандарты, такие как тестирование проблем с шасси (отлично для самолетов, неактуально для поездов) или чрезмерно беспокоиться о маловероятных событиях, таких как случайная телепортация, прежде чем вы бы не закрепили основы.

Когда мы думаем о реальных сценариях, мы естественно склонны думать о ключевых рисках и механистических причинах. Однако в более абстрактном мире данных многие наши тесты данных часто склоняются к одной из двух крайностей: применению шаблонных тестов (null, PK-FK отношения и т.д.) из мира традиционного управления базами данных или игре с новыми инструментами, которые обещают поймать наши самые дикие ошибки с помощью обнаружения аномалий и искусственного интеллекта.

Между этими двумя крайностями лежит разрыв, который заполняется человеческим интеллектом. Инженеры аналитики могут создавать более эффективные тесты, внедряя свое понимание того, как были созданы данные, и особенно как эти данные могут пойти наперекосяк (тема, о которой я писала ранее). Хотя такие выразительные тесты будут уникальны для нашей области, скромные изменения в нашем мышлении могут помочь нам реализовать их с помощью наших стандартных инструментов. Этот пост демонстрирует, как простое проведение тестов по группам может расширить вселенную возможных тестов, повысить чувствительность существующего набора и помочь держать наши данные "на правильном пути". Эта функция теперь доступна в dbt-utils.

Групповые проверки

Проверки на основе групп могут быть важны для полного формулирования хороших "бизнес-правил", по которым можно оценивать качество данных. Например, группы могут отражать либо вычислительно значимые измерения процесса (например, данные, загруженные из разных источников), либо семантически значимые измерения реального процесса, который наши данные фиксируют (например, повторяющиеся измерения, относящиеся к многим отдельным клиентам, пациентам, продуктовым линиям и т.д.). Такие проверки могут сделать существующие тесты более строгими, в то время как другие могут быть выражены только на уровне групп.

Только выражаемые

Некоторые типы проверок могут быть выражены только по группам. Например, в наборе данных, содержащем расписания поездов по всей транспортной системе, поле ARRIVAL_TIME может не быть уникальным; однако оно (надеемся) всегда будет уникальным для конкретного TRACK и STATION!

Более строгие

Рассмотрим проверку актуальности (т.е. что максимальная дата, представленная в данных, соответствует настоящему времени); если данные загружаются из нескольких источников (например, покупка билетов через веб, мобильное приложение или киоск на станции), проверка максимальной даты может пройти, если загружен хотя бы один источник, но если данные не сгруппированы по источнику и не проверена максимальная дата каждой группы, устаревшие данные могут остаться незамеченными.

Исследование: данные метро Нью-Йорка

Чтобы продемонстрировать полезность (или, лучше сказать, необходимость) проверок на уровне групп, давайте рассмотрим некоторые реальные открытые данные из системы метро Нью-Йорка, на которые я всегда могу рассчитывать, чтобы обнаружить множество особенностей качества данных (что, чтобы было ясно, я не говорю как критику; в реальном мире "данные как остаток" это не является неожиданностью). Кумулятивные записи через каждый турникет на всех станциях метро фиксируются 4 раза в день, создавая структуру с одной записью для каждой комбинации турникета и временной метки.

Конечно, информация, которую мы хотим получить из этих данных, вероятно, не является кумулятивным счетом через какой-то турникет с какой-то произвольной начальной даты, а скорее записями на уровне станции за определенный период. Таким образом, в наших преобразованиях мы бы взяли отложенную разницу кумулятивных записей по турникету и агрегировали бы это на уровне станции. Просто собирая данные с 5000 датчиков – что может пойти не так, верно?

Однако это, казалось бы, тривиальное преобразование с отложенной разницей делает два ключевых предположения: кумулятивные записи по турникету и каждое временное наблюдение присутствует для каждого турникета.

Эти условия иллюстрируют две выгоды от групповых проверок, которые мы упомянули ранее: монотонность может быть оценена только после группировки по турникету (нет причин, по которым кумулятивный счет записей должен только увеличиваться при сравнении наблюдений по разным турникетам), и хотя наличие данных временных меток может быть проверено на уровне набора данных, это значительно более строго, когда проверяется на уровне отдельного датчика.

Итак, что мы обнаруживаем, когда проверяем наши данные по группам?

Проверяя монотонность, мы находим много плохо работающих турникетов. В отличие от хорошо работающей темно-синей линии, другие турникеты, кажется, уменьшаются вместо увеличения с каждым оборотом, в то время как другие циклически увеличиваются и падают до нуля – возможно, из-за событий технического обслуживания, замен или сбоев в связи с центральным сервером.

График с тремя линиями: одна темно-синяя, направленная вверх и вправо, одна светло-синяя, направленная вниз и вправо, и одна очень светло-синяя, которая идет вверх, а затем внезапно падает, повторяясь в виде зубчатого узора.Кумулятивные записи по турникету для 3 турникетов

Аналогично, хотя ни одна ожидаемая временная метка не отсутствует в данных полностью, более строгая проверка временных меток по турникету выявляет от 50 до 100 отсутствующих наблюдений за любой данный период.

Точечный график, показывающий, что 50-100 турникетов отсутствуют для каждого периода между январем и маем, диапазон показан на оси x.Количество отсутствующих турникетов по времени записи

Посмотрите этот GitHub gist, чтобы воспроизвести эти представления локально.

Оптимизация групповых проверок

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

Так же, как мы не можем осмотреть каждую шпалу на нашей железнодорожной линии, групповые проверки представляют собой компромисс между усилиями (как когнитивными, так и вычислительными!) и ценностью. Они наиболее эффективны, когда группы связаны с конкретными точками трения в нашем конвейере, которые мы не можем протестировать или контролировать, что происходит дальше по потоку.

Не все группировки одинаково вероятно нарушат данные. В примере с метро, сбои на уровне турникетов вероятны, потому что каждый отдельный турникет независимо участвует в сборе данных и может ломаться по-своему. Однако, если бы мы работали с данными о кликах для нашего онлайн-портала продажи билетов, процесс сбора данных централизован, поэтому маловероятно, что ETL сломается по-особенному для каждого клиента, и было бы обременительно выполнять проверки по клиентам.

Даже когда групповые проверки имеют смысл, их необходимость может быть "запахом кода", который указывает на то, что мы могли бы вместо этого выполнять более простые проверки дальше по потоку. Поскольку групповые проверки чаще всего необходимы для противодействия смешиванию нескольких происхождений данных, где это возможно, их можно переписать как более типичные тесты, применяемые к каждой ветви происхождения до консолидации. Например, было бы неплохо, если бы мы могли проверить монотонность до агрегирования данных датчиков. Однако, когда у нас нет контроля над этими процессами выше по потоку, групповые проверки предлагают практическую альтернативу.

Теперь в dbt-utils!

Если вас заинтересовала перспектива групповых проверок, теперь можно запускать эти тесты из dbt-utils. Выпуск 1.0.0 добавляет группировку в тесты для всех релевантных тестов, в частности:

  • equal_rowcount()
  • fewer_rows_than()
  • recency()
  • at_least_one()
  • not_constant()
  • sequential_values()
  • non_null_proportion()

Каждая проверка теперь имеет аргумент group_by_columns, который принимает одно или несколько имен столбцов. Например, чтобы проверить наличие действительной ежедневной записи для каждого турникета на каждой станции, мы могли бы добавить в наш файл schema.yml:

models:
  - name: turnstile_entries
    tests:
- dbt_utils.recency:
         datepart: day
          field: recorded_at
          interval: 1
# Проверка актуальности для каждого turnstile_id на каждой station_id
          group_by_columns:
            - station_id
            - turnstile_id

Заключение

И что делать, если ваши новые тесты данных не проходят? Это на самом деле раскрывает последнюю выгоду от проверок, основанных на гипотезах: поскольку вы тестируете на сбой конкретных систем или процессов, результаты тестов направят ваше внимание на отладку к коренной причине вашей проблемы с данными! Вместо того чтобы отправляться в бесцельный поиск, вы сразу узнаете, на каком этапе вашего конвейера сосредоточить внимание, чтобы вернуть вашу систему на правильный путь.

Comments

Loading