Ana içeriğe geç
Kesit SQL
İleri · Veri Bilimi

Zaman serisi özellikleri

Gecikmeli değerler, hareketli ortalamalar, mevsimsel özellikler.

Uygulamada aç, 3 alıştırmayı çözÜcretsiz, hesap gerekmez, kurulum yok.

Bu sayfa dersin okuma sürümüdür. Metin bir kutuyu çalıştırmanı ya da adıma geçmeni söylüyorsa dersi uygulamada aç.

Tahmin modelleri için tablo

Günlük sipariş tahmini yapan bir model; dünün, geçen haftanın aynı gününün değerine ve hareketli ortalamalara ihtiyaç duyar.

WITH RECURSIVE gun(d) AS (
  SELECT '2024-10-01' UNION ALL SELECT date(d, '+1 day') FROM gun WHERE d < '2024-12-31'
),
g AS (
  SELECT gun.d, COUNT(o.order_id) AS y
  FROM gun LEFT JOIN orders o ON o.order_date = gun.d
  GROUP BY gun.d
)
SELECT d, y,
       LAG(y, 1) OVER w AS lag_1,
       LAG(y, 7) OVER w AS lag_7,
       ROUND(AVG(y) OVER (ORDER BY d ROWS BETWEEN 7 PRECEDING AND 1 PRECEDING), 2) AS ort_7_onceki,
       CAST(strftime('%w', d) AS INTEGER) AS hafta_gunu,
       CASE WHEN CAST(strftime('%w', d) AS INTEGER) IN (0, 6) THEN 1 ELSE 0 END AS hafta_sonu
FROM g
WINDOW w AS (ORDER BY d)
ORDER BY d;

Dikkat: Hareketli ortalama 1 PRECEDING'de bitiyor. Bugünün değerini içeren bir özellik, bugünü tahmin ederken sızıntı olur.

Özellik türleri

TürÖrnekSQL
Gecikme (lag)Dünün, geçen haftanın aynı gününün değeriLAG(y, 1), LAG(y, 7)
Hareketli istatistikSon 7 günün ortalaması, en büyüğüAVG(y) OVER (ORDER BY d ROWS BETWEEN 7 PRECEDING AND 1 PRECEDING)
TakvimHaftanın günü, ay, hafta sonu, tatilTarih fonksiyonları ve bir tatil tablosuyla birleştirme
Fark ve oranGeçen haftaya göre değişimy - LAG(y, 7), y * 1.0 / NULLIF(LAG(y, 7), 0)

Boş günleri doldurmak şart

Sipariş olmayan günler tabloda yoksa LAG(y, 7) yedi takvim günü öncesine değil, yedi satır öncesine bakar. Bu yüzden yukarıdaki örnek önce özyinelemeli CTE ile tüm günleri üretiyor, siparişleri LEFT JOIN ile bağlıyor ve eksik günler 0 sayılıyor.

Eğitim ve test ayrımı zamana göre yapılır

Zaman serisinde satırları rastgele bölmek, modelin geleceği görerek geçmişi tahmin etmesine yol açar. Bir kesim tarihi seçilir: öncesi eğitim, sonrası test.

WITH m AS (
  SELECT strftime('%Y-%m', order_date) AS ay, COUNT(*) AS y
  FROM orders
  GROUP BY strftime('%Y-%m', order_date)
)
SELECT ay, y,
       LAG(y) OVER (ORDER BY ay) AS lag_1,
       CASE WHEN ay < '2024-10' THEN 'egitim' ELSE 'test' END AS bolum
FROM m
ORDER BY ay;
Özellikler de kesim tarihine uymalıTest dönemindeki bir satırın özellikleri yalnızca o satırdan önceki veriden hesaplanabilir. Pencere çerçevesini 1 PRECEDING'de bitirmek bu kuralın SQL'deki karşılığıdır.
Alıştırmalara geç (3)