İçeriğe geç
academia.sh

Ders 07 / 09

Veri Kaynakları

Aynı büyüklük — ortalama aylık tüketim — üç kaynaktan üç farklı sayı verir: saha anketi 22,42 m³, faturalama özetinden yeniden kurulan değer 21,59 m³, sayaç telemetrisi 17,01 m³, modelin doğrusu ise 21,31 m³. Abone sayısı bile kaynağa göre 1.400, 886 ve 1.041 çıkar. Her kaynakta tek bir karar değiştirildiğinde altı sayı 14,11 ile 22,42 m³ arasına yayılır ve hiçbirinde hesap hatası yoktur; yanlılığın kaynağı kapsam tablosunda görülür.

İçindekiler

Önceki iki ders alanların türünü ve ölçeğini sordu, ama ikisi de 1.400 satırı hazır kabul etti. Bu ders satırların nereden geldiğini sorar ve tek bir büyüklüğü — bir aylık ortalama tüketimi — üç ayrı kaynaktan ölçer. Üç sayı da doğru toplanmıştır ve üçü de farklıdır.

Fark bir hesap hatasından çıkmaz. Her kaynak, kimin kayda girdiğine dair bir karar taşır ve o karar veriyle birlikte gelmez; kaynağın kurulma biçiminde saklıdır. Bir anket yalnız yanıt verenleri, bir telemetri akışı yalnız iletebilen cihazları, bir özet raporu yalnız yayımlanmış kırılımı içerir. Ölçü bu dersin sonunda kaynağın taşıdığı yanlılıktır: kaynağın verdiği sayı ile gerçeğin arasındaki fark ve o farkın hangi kayıtların dışarıda kalmasından geldiği.

  • VY10. Küme, önceki derslerin 1.400 satırlık abone kaydıdır. Küme kurgudur ve bu dersin ayrıcalığı şudur: modelin doğrusu bilinir. Gerçek ortalama tüketim 21,31 m³’tür ve hiçbir kaynak bu sayıyı görmez.
  • VY11. Birincil veri (primary data), çözümlemeyi yapan tarafın kendi topladığı veridir: saha ziyaretinde doldurulan hane anketi. Kapsamı iki kararla belirlenir — kim ziyaret edildi ve kim yanıt verdi.
  • VY12. İkincil veri (secondary data), başkasının başka bir amaçla toplayıp yayımladığı veridir: faturalama sisteminin tarife basamağı özeti. Ham satırlar yoktur, yalnız basamak sayıları vardır.
  • VY13. Üretilen veri (generated data), bir düzeneğin işleyişi sırasında kendiliğinden biriken veridir: sayaçların gönderdiği telemetri. Kimse doldurmaz, ama cihazın iletememesi de bir kayıt kararıdır.
  • VY14. Modelde yanıt verme olasılığı tüketimle artar, iletim olasılığı tüketimle azalır, telemetri her ay 20 ile 30 gün arası veri gönderir. Bu üç eğilim modele girdi olarak verilmiştir; kaynağın yapısını temsil ederler.

Üç Kaynak, Üç Sayı

// kaynaklar.mjs — ayni buyuklugu uc kaynaktan olcen model.
export const TOHUM = 20260218, KAYIT = 1400, TARIFE = [10, 25, 40];
const karistir = (x) => { x = Math.imul(x ^ (x >>> 16), 2246822507);
  x = Math.imul(x ^ (x >>> 13), 3266489909); return (x ^ (x >>> 16)) >>> 0; };
const uretec = (t) => { let s = karistir(t);
  return () => (s = (s * 1664525 + 1013904223) >>> 0) / 4294967296; };
const ayrik = (u, w) => { let t = 0;
  for (let i = 0; i < w.length; i++) { t += w[i]; if (u < t) return i; } return w.length - 1; };
export const BOLGE = [
  { ad: "kuzey", pay: 0.28, taban: 21, mem: [0.05, 0.10, 0.25, 0.40, 0.20] },
  { ad: "guney", pay: 0.22, taban: 17, mem: [0.02, 0.08, 0.30, 0.45, 0.15] },
  { ad: "dogu", pay: 0.18, taban: 26, mem: [0.20, 0.08, 0.05, 0.12, 0.55] },
  { ad: "bati", pay: 0.14, taban: 14, mem: [0.10, 0.15, 0.25, 0.30, 0.20] },
  { ad: "merkez", pay: 0.18, taban: 23, mem: [0.06, 0.12, 0.28, 0.34, 0.20] },
];
export const KAYITLAR = Array.from({ length: KAYIT }, (_, i) => {
  const r = uretec(TOHUM + i);
  const b = BOLGE[ayrik(r(), BOLGE.map((x) => x.pay))];
  const t = Math.max(1.2, b.taban * Math.exp((r() + r() + r() - 1.5) * 0.62));
  const tuketim = Math.round(t * 100) / 100;
  const sayac = ayrik(r(), [0.62, 0.24, 0.10, 0.04]) + 1;
  const ziyaret = ayrik(r(), [0.38, 0.32, 0.16, 0.08, 0.04, 0.02]);
  const memnuniyet = ayrik(r(), b.mem) + 1;
  const sicaklik = Math.round((6 + r() * 22) * 10) / 10;
  const gecen = Math.floor(Math.pow(r(), 1.9) * 210);
  // Kaynak cizimleri taban alanlardan SONRA yapilir; taban kume degismez.
  const yanit = r() < 0.30 + 0.014 * tuketim;   // yuksek tuketen daha cok yanit verir
  const iletim = r() < 0.95 - 0.010 * tuketim;  // yuksek debide iletim daha cok kesilir
  const kapsananGun = 30 - Math.floor(r() * 11); // cihazin ay icinde raporladigi gun
  return { abone_no: 10001 + i, bolge: b.ad, tuketim_m3: tuketim, sayac_sayisi: sayac,
    ziyaret_sayisi: ziyaret, memnuniyet, sicaklik_c: sicaklik, gecen_gun: gecen,
    yanit, iletim, kapsananGun,
    basamak: tuketim < TARIFE[0] ? 1 : tuketim < TARIFE[1] ? 2 : tuketim < TARIFE[2] ? 3 : 4 };
});
export const ort = (a) => a.reduce((x, y) => x + y, 0) / a.length;
const GERCEK = ort(KAYITLAR.map((k) => k.tuketim_m3));

// Birincil: saha ziyaretinde toplanan hane anketi (ziyaret alan ve yanit veren).
export const birincil = KAYITLAR.filter((k) => k.ziyaret_sayisi >= 1 && k.yanit);
// Ikincil: faturalama ozetinden basamak sayilariyla yeniden kurulan ortalama.
export const ORTA = [5, 17.5, 32.5, 50];
export const ikincilOrt = (temsil) => {
  let t = 0;
  for (let b = 1; b <= 4; b++) t += KAYITLAR.filter((k) => k.basamak === b).length * temsil[b - 1];
  return t / KAYIT;
};
// Uretilen: sayac telemetrisi; yalnizca ileten cihazlar, eksik gunler oldugu gibi.
export const uretilen = KAYITLAR.filter((k) => k.iletim);
const telemetriHam = (k) => k.tuketim_m3 * k.kapsananGun / 30;

const gen = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j])
  : String(v).padEnd(B[0]))).join("");

if (import.meta.url === `file://${process.argv[1]}`) {
  console.log(`model (tohum ${TOHUM}): ${KAYIT} abone; modelin dogrusu ` +
    `ortalama ${GERCEK.toFixed(2)} m3`);
  const y = gen([28, 9, 9, 12, 10]);
  console.log("\n" + y(["kaynak", "kayit", "kapsam", "ortalama", "sapma"]));
  const satirlar = [
    ["birincil: saha anketi", birincil.length, ort(birincil.map((k) => k.tuketim_m3))],
    ["ikincil: faturalama ozeti", KAYIT, ikincilOrt(ORTA)],
    ["uretilen: sayac telemetrisi", uretilen.length, ort(uretilen.map(telemetriHam))],
  ];
  for (const [ad, n, o] of satirlar) {
    console.log(y([ad, n, `%${(100 * n / KAYIT).toFixed(1)}`, o.toFixed(2),
      (o - GERCEK >= 0 ? "+" : "") + (o - GERCEK).toFixed(2)]));
  }
  console.log(`\nabone sayisi da kaynaga gore degisir: kayit sisteminde ${KAYIT}, ` +
    `saha listesinde ${KAYITLAR.filter((k) => k.ziyaret_sayisi >= 1).length}, ` +
    `telemetride ${uretilen.length} cihaz`);
  const uc = satirlar.map((s) => s[2]);
  console.log(`uc kaynagin en buyuk farki ${(Math.max(...uc) - Math.min(...uc)).toFixed(2)} m3`);
}
model (tohum 20260218): 1400 abone; modelin dogrusu ortalama 21.31 m3

kaynak                          kayit   kapsam    ortalama     sapma
birincil: saha anketi             544    %38.9       22.42     +1.11
ikincil: faturalama ozeti        1400   %100.0       21.59     +0.28
uretilen: sayac telemetrisi      1041    %74.4       17.01     -4.30

abone sayisi da kaynaga gore degisir: kayit sisteminde 1400, saha listesinde 886, telemetride 1041 cihaz
uc kaynagin en buyuk farki 5.41 m3

Üç kaynak aynı 1.400 aboneyi kapsamak üzere kurulmuştur ve hiçbiri kapsamaz. Saha anketi 544 kayda, telemetri 1.041 cihaza ulaşır; faturalama özeti sayı olarak hepsini kapsar ama ham satırı göstermez. Sapma sütunu üç farklı yön gösteriyor: anket 1,11 m³ yukarı, özet 0,28 m³ yukarı, telemetri 4,30 m³ aşağı. En büyük fark 5,41 m³’tür ve bu, gerçek değerin dörtte birine yakındır.

Son satır daha rahatsız edicidir. Abone sayısı bile kaynağa göre değişir: kayıt sisteminde 1.400, saha listesinde 886, telemetride 1.041. “Kaç abonemiz var” sorusunun tek bir cevabı yoktur; her sayı bir kapsam tanımının cevabıdır. Bir raporda abone sayısı yazılırken hangi kaynağın sayıldığı belirtilmiyorsa, o sayı üç farklı büyüklükten biridir ve hangisi olduğu okunamaz.

Telemetrinin 4,30 m³’lük sapması iki ayrı nedenden gelir ve ikisi de kaynağın yapısına aittir. Cihazlar ayın tamamını değil 20 ile 30 gün arasını raporlar, bu yüzden ham toplam bir aylık tüketimin altında kalır. Ayrıca iletim olasılığı yüksek tüketimde düşer, yani eksik kalan cihazlar rastgele seçilmiş değildir. Bir kaynak eksik veri verdiğinde asıl soru ne kadarının eksik olduğu değil, eksik olanların hangileri olduğudur.

Kararı Değiştirince

Kapsam kaynağın kararıdır. Bir de çözümlemeyi yapanın kararı vardır: eldeki kayıtlardan sayıyı nasıl çıkaracağı. Aşağıdaki blok her kaynakta tek bir kararı değiştirir.

// karar.mjs — her kaynakta tek bir karar degistirilir, iki sayi yan yana basilir.
import { KAYITLAR, KAYIT, ort, birincil, uretilen, ikincilOrt, ORTA } from "./kaynaklar.mjs";
const GERCEK = ort(KAYITLAR.map((k) => k.tuketim_m3));
const pay = (b) => KAYITLAR.filter((k) => k.basamak === b).length / KAYIT;
// Basamak paylari faturalama ozetinden bilinir; ornek bu paylara geri agirliklanir.
const agirlikli = (l) => { let t = 0;
  for (let b = 1; b <= 4; b++) { const alt = l.filter((k) => k.basamak === b);
    if (alt.length) t += pay(b) * ort(alt.map((k) => k.tuketim_m3)); }
  return t; };
const satir = [
  ["birincil", "A: yanit verenlerin ham ortalamasi", ort(birincil.map((k) => k.tuketim_m3))],
  ["birincil", "B: basamak paylarina geri agirliklama", agirlikli(birincil)],
  ["ikincil", "A: her basamak orta noktasiyla", ikincilOrt(ORTA)],
  ["ikincil", "B: her basamak alt siniriyla", ikincilOrt([0, 10, 25, 40])],
  ["uretilen", "A: eksik gunler oldugu gibi toplanir",
    ort(uretilen.map((k) => k.tuketim_m3 * k.kapsananGun / 30))],
  ["uretilen", "B: kapsanan gune gore aya olceklenir", ort(uretilen.map((k) => k.tuketim_m3))],
];
const y = (h) => String(h[0]).padEnd(11) + String(h[1]).padEnd(39)
  + String(h[2]).padStart(9) + String(h[3]).padStart(9);
console.log(y(["kaynak", "karar", "sayi", "sapma"]));
for (const [k, a, s] of satir) {
  console.log(y([k, a, s.toFixed(2), (s - GERCEK >= 0 ? "+" : "") + (s - GERCEK).toFixed(2)]));
}
const s = satir.map((x) => x[2]);
console.log(`\nmodelin dogrusu ${GERCEK.toFixed(2)} m3; alti sayinin hicbirinde hesap ` +
  `hatasi yok`);
console.log(`kaynak ici en buyuk fark ${Math.max(...[0, 2, 4].map((i) =>
  Math.abs(s[i + 1] - s[i]))).toFixed(2)} m3, alti sayinin araligi ` +
  `${Math.min(...s).toFixed(2)} - ${Math.max(...s).toFixed(2)} m3`);
console.log(`uc kaynagin A kararlarinin ortalamasi ` +
  `${ort([s[0], s[2], s[4]]).toFixed(2)} m3 — ardinda tek bir karar yoktur`);

// Yanliligin kaynagi: hangi kayitlarin kapsam disinda kaldigi.
console.log(`\nkapsam basamak basamak`);
const y2 = (h) => String(h[0]).padEnd(10) + h.slice(1).map((v) => String(v).padStart(12)).join("");
console.log(y2(["basamak", "tum kume", "ankette", "ankette %", "telemetride", "telemetri %"]));
for (const b of [1, 2, 3, 4]) {
  const t = KAYITLAR.filter((k) => k.basamak === b).length;
  const a = birincil.filter((k) => k.basamak === b).length;
  const u = uretilen.filter((k) => k.basamak === b).length;
  console.log(y2([b, t, a, `%${(100 * a / t).toFixed(1)}`, u, `%${(100 * u / t).toFixed(1)}`]));
}
kaynak     karar                                       sayi    sapma
birincil   A: yanit verenlerin ham ortalamasi         22.42    +1.11
birincil   B: basamak paylarina geri agirliklama      21.52    +0.21
ikincil    A: her basamak orta noktasiyla             21.59    +0.28
ikincil    B: her basamak alt siniriyla               14.11    -7.19
uretilen   A: eksik gunler oldugu gibi toplanir       17.01    -4.30
uretilen   B: kapsanan gune gore aya olceklenir       20.48    -0.83

modelin dogrusu 21.31 m3; alti sayinin hicbirinde hesap hatasi yok
kaynak ici en buyuk fark 7.48 m3, alti sayinin araligi 14.11 - 22.42 m3
uc kaynagin A kararlarinin ortalamasi 20.34 m3 — ardinda tek bir karar yoktur

kapsam basamak basamak
basamak       tum kume     ankette   ankette % telemetride telemetri %
1                   48          15       %31.3          43       %89.6
2                  970         351       %36.2         754       %77.7
3                  348         159       %45.7         224       %64.4
4                   34          19       %55.9          20       %58.8

Altı sayı 14,11 ile 22,42 m³ arasına yayılıyor ve hepsi aynı aboneleri, aynı ayı, aynı büyüklüğü anlatıyor. Kaynak içinde en büyük fark 7,48 m³’tür — kaynaklar arası farktan büyüktür. Bu, dersin en önemli sayısıdır: hangi kaynağı seçtiğin kadar, o kaynağı nasıl işlediğin de sayıyı oynatır.

İkincil kaynağın iki kararı aynı soruya cevap vermiyor ve bu ayrım yazılmadıkça iki sayı karşılaştırılamaz. Basamak orta noktası kullanmak bir tahmindir; basamak alt sınırı kullanmak bir alt sınırdır ve “abonelerin en az ne kadar tükettiğini” cevaplar. Rapor edilen 14,11 m³ yanlış değildir, ama 21,59 ile yan yana konduğunda okuyucu iki tahmin gördüğünü sanır. Bir sayının tahmin mi sınır mı olduğu, o sayının kendisinden okunamaz.

Birincil kaynakta geri ağırlıklama sapmayı 1,11’den 0,21 m³’e indiriyor. Düzeltmenin bedeli şudur: ağırlıklar başka bir kaynaktan, faturalama özetinden gelir. Yanlılığı gidermek için ikinci bir kaynağa gerek duyuldu ve o kaynağın da kendi kararları var. Telemetride kapsanan güne göre ölçekleme sapmayı 4,30’dan 0,83 m³’e indiriyor; kalan 0,83 m³ ikinci nedenden, yüksek tüketen cihazların iletmemesinden gelir ve gün ölçeklemesi ona dokunmaz. Bir kararı düzeltmek yanlılığın tamamını gidermez; her kararın kapattığı boşluk ayrıdır.

Son tablo yanlılığın nereden geldiğini yazıyor. Ankette birinci basamaktaki abonelerin yüzde 31,3’ü, dördüncü basamaktakilerin yüzde 55,9’u var: yüksek tüketenler örnekte fazla temsil ediliyor, bu yüzden ortalama yukarı kayıyor. Telemetride yön tersine dönüyor — birinci basamağın yüzde 89,6’sı iletirken dördüncü basamağın yalnız yüzde 58,8’i iletiyor. İki kaynak da aynı ağdan, aynı ayda, aynı abonelerden beslenir ve zıt yönde yanlıdır. Yanlılık verinin bir özelliği değil, kaynağın kapsam kararının bir sonucudur; kapsam tablosu yazılmadan hiçbir sapma açıklanamaz.

Üç kaynağın ortalamasını almak — 20,34 m³ — bu tabloyu yok saymaktır. O sayının ardında tek bir karar yoktur; üç ayrı kapsam kararının aritmetik ortalamasıdır ve hangi soruyu cevapladığı belirsizdir.

Özet

  • Aynı büyüklük üç kaynakta üç sayı verir: saha anketi 22,42, faturalama özeti 21,59, telemetri 17,01 m³; modelin doğrusu 21,31 m³’tür ve hiçbir kaynak onu görmez.
  • Abone sayısı da kaynağa göre değişir — 1.400, 886, 1.041 — ve hangisinin sayıldığı yazılmadan bu sayı okunamaz.
  • Kaynak içinde işleme kararının açtığı fark 7,48 m³’e çıkar ve kaynaklar arası farktan büyüktür.
  • Bir tahmin ile bir alt sınır aynı biçimde yazılır ve ayırt edilemez: 21,59 bir tahmindir, 14,11 bir alt sınırdır ve ikisi de aynı özetten çıkar.
  • Yanlılık kapsam kararından gelir: ankette dördüncü basamağın yüzde 55,9’u, telemetride yüzde 58,8’i vardır ve iki kaynak zıt yönde yanlıdır.

Sonraki Adım

Bu ders kaynağın hangi kayıtları dışarıda bıraktığını ölçtü, ama içeri alınan kayıtları sorgusuz kabul etti: 544 anket satırının hepsi doğru doldurulmuş, 1.041 telemetri kaydının hepsi tutarlı sayıldı. Gerçek bir kümede bu geçerli değildir. Bir okuma fiziksel olarak imkânsız olabilir, bir alan boş kalabilir, iki alan birbiriyle çelişebilir, bir kayıt aylar önce yazılmış olabilir. Sonraki ders bu dört soruyu dört ölçülebilir boyuta çevirir ve her biri için bir sayı üretir; sonra eşikleri sıkılaştırıp kaç satırın elendiğini ve elenen satırların rapor edilen sayıyı hangi yöne ittiğini gösterir.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat