Data Analyst Professional · Модуль 6 · Урок 20 із 51

Пропуски, дублікати й аномалії: рішення без втрати доказів

NULL, blank, duplicate та outlier — це сигнал, а не автоматична команда «видалити». Спочатку визначте причину, бізнес-сенс і вплив; потім оберіть quarantine, correction, imputation, exclusion або прийняття з disclosure.

90–120 хвQuarantine firstМінітест: 3 питання

Missingness має різні причини

СтанПрикладБезпечне рішення
not applicablerefund_reason для paidзалишити NULL і задокументувати
not collectedстарий source не мав regionпозначити source/version
collection errorобов’язковий customer_ref відсутнійquarantine + upstream fix
unknownнемає доказу причинине вигадувати value; disclosure

COALESCE не «виправляє» якість. Підстановка zero або “unknown” змінює значення метрики і допустима лише за визначеним правилом.

Дублікати: спочатку ключ і survivorship

SELECT source_system, customer_ref, event_ts_text, amount_text, COUNT(*) AS duplicate_rows, ARRAY_AGG(source_row_id ORDER BY source_row_id) AS evidence_rows FROM seowork_lab.raw_customer_events GROUP BY 1,2,3,4 HAVING COUNT(*) > 1;

Exact row duplicate, duplicate business key і кілька законних events — різні випадки. Для dedup задайте match key, winner rule, tie-breaker і збережіть rejected rows у quarantine з reason code.

ROW_NUMBER() OVER ( PARTITION BY source_system, normalized_customer_ref, parsed_event_ts, parsed_amount ORDER BY loaded_at DESC, source_row_id DESC ) AS survivor_rank

Аномалія не дорівнює помилці

Hard invalid

Impossible date, negative amount за забороненим rule, status поза dictionary.

Statistical outlier

Рідкісне, але можливе значення; потрібен контекст і robust method.

Business exception

VIP order або разова акція; не видаляти без owner.

Pipeline defect

Стрибок після release/source change; потрібен incident і upstream fix.

Для skewed distributions median/IQR або percentile rules часто кращі за довільний average ± threshold. Outlier flag має бути окремим полем, а raw value — збереженим.

Quarantine pattern

CREATE TABLE clean_events AS SELECT *, CASE WHEN customer_ref IS NULL OR BTRIM(customer_ref) = '' THEN 'MISSING_KEY' WHEN status_text NOT IN ('paid','cancelled','refunded') THEN 'INVALID_STATUS' ELSE NULL END AS rejection_reason FROM seowork_lab.raw_customer_events;-- valid scope: rejection_reason IS NULL -- quarantine: rejection_reason IS NOT NULL

У production краще не змішувати clean і quarantine фізично без чіткого доступу, але навчальний pattern показує головне: кожна втрата рядка має причину та count.

Практика

  • Порахуйте NULL окремо від blank/whitespace.
  • Знайдіть exact і business-key duplicates.
  • Запропонуйте deterministic survivorship rule.
  • Позначте hard-invalid і suspicious rows, не перезаписуючи raw.
  • Звірте raw = accepted + quarantined за rows і control amounts.

Офіційні джерела

Готовність до тесту

Ви не плутаєте missing reasons, визначаєте duplicate через grain/key, відділяєте anomaly від error і зберігаєте audit trail через quarantine.

Практична перевірка · урок 20 з 51

Закріпіть матеріал уроку

Три сценарні питання. Для зарахування уроку потрібно дати щонайменше дві правильні відповіді.

1. Чи треба автоматично замінювати всі NULL на zero?
2. Що таке not applicable missingness?
3. Від чого залежить визначення duplicate?