İçeriğe geç
academia.sh

Ders 14 / 17

Gruplama ve Toplulaştırma

3.199 satırlık küme dört gruplama kararıyla 5, 15, 53 ve 1.260 satıra iner; bölge, tarife basamağı ve dönem çaprazının 60 gözünden 7'si hiç satır taşımaz ve çıktıda hiç görünmez. Aynı kümeden üç genel ortalama çıkar: 3.199 satırdan 19,713 m³, beş bölge satırından 19,532 m³, 53 hücreden 20,721 m³. Beş satırlık özet 3.199 okumanın 431'inin kendi grup ortalamasından yüzde elliden fazla saptığını, 58 okumanın 40 m³'ü aştığını ve doğu ile batı bölgelerinin 50 okumada yer değiştirdiğini taşımaz.

İçindekiler

Bir önceki ders kümenin şeklini değiştirdi ama tek bir değeri bile birleştirmedi: 3.199 ölçüm, 1.260 satırlık geniş biçimde de 3.199 ayrı hücrede duruyordu. Rapora giren sayı ise nadiren bir hücredir. “Bölge başına ortalama tüketim” sorusu 3.199 satırı beş satıra indirir ve bu indirme, önceki dersteki şekil değişiminden farklı olarak geri alınamaz.

Elektronik Tablolarla Analiz kursundaki Özet Tablolar dersi bu kararı bir sayfada ölçmüş ve aynı sayfadan beş özet kararının üç farklı bölgeyi birinci yaptığını göstermişti. Bu ders aynı işi betik tarafında ve başka bir ölçüyle ele alır: hangi bölgenin birinci olduğu değil, kaç satır kaldığı ve kaybolanın ne olduğu sayılır.

  • VD11. Toplulaştırma, bir grubun satırlarını tek bir satıra indiren işlemdir. Çıkan satır sayısı hesabın değil, gruplama alanının tekil değer sayısının sonucudur.
  • VD12. Çapraz kırılımda olası göz sayısı alanların tekil değerlerinin çarpımıdır. Hiç satır taşımayan göz çıktıda hiç görünmez ve okuyucu için “sıfır” ile “veri yok” ayırt edilemez.
  • VD13. Toplulaştırılmış satırlar yeniden toplulaştırıldığında her grup eşit ağırlık alır. Bu, ham satırlardan hesaplanan sayıdan farklı bir sayı verir ve fark grup boyutlarının eşitsizliğinden gelir.
  • VD14. Bir özet satırı grubun merkezini taşır, yayılımını taşımaz. Yayılım ayrıca hesaplanıp yanına yazılmazsa kaybolur ve geri getirilemez.
  • VD15. Kaybın ölçüsü, özetten cevaplanamayan sorulardır: özet satırından okunan cevapla ham satırlardan okunan cevap yan yana konur.

Kaç Satır Kalıyor

// grupla.mjs — MODELDIR: onceki dersin uzun bicimli kumesi ve dort gruplama
// karari. Veri kumesi kurgudur; hicbir sorgu arayuzu taklit edilmez.
export const TOHUM = 20260218, HAM = 1400, DONEM = ["2026-01", "2026-02", "2026-03"];
export const 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; };
const BOLGE = [["kuzey", 0.28, 21], ["guney", 0.22, 17], ["dogu", 0.18, 26],
  ["bati", 0.14, 14], ["merkez", 0.18, 23]];
const ABONE = [], ELENEN = [];
for (let i = 0; i < HAM; i++) {
  const r = uretec(TOHUM + i), b = BOLGE[ayrik(r(), BOLGE.map((x) => x[1]))];
  const k = { abone_no: 10001 + i, bolge: b[0], taban: b[2],
    hane_kisi: ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05]),
    memnuniyet: ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17]) + 1 };
  (r() < 0.046 ? ELENEN : ABONE).push(k);
}
const anahtar = new Set(ABONE.map((a) => a.abone_no)), ham = [];
for (const k of [...ABONE, ...ELENEN]) {
  const r = uretec(TOHUM + 7000 + k.abone_no), adet = ayrik(r(), [0.05, 0.12, 0.21, 0.62]);
  for (let d = 0; d < adet; d++) {
    const t = r() < 0.038 ? 0 : Math.round(k.taban * Math.exp((r() + r() + r() - 1.5) * 0.62)
      * (1 - d * 0.05) * 100) / 100;
    if (!anahtar.has(k.abone_no)) { r(); continue; }
    ham.push({ abone_no: k.abone_no, bolge: k.bolge, donem: DONEM[d], tuketim_m3: t });
    if (r() < 0.028) ham.push({ abone_no: k.abone_no, bolge: k.bolge, donem: DONEM[d],
      tuketim_m3: Math.round(t * 1.02 * 100) / 100 });
  }
}
// Onceki dersin kapanis kumesi; tarife basamagi okumadan turetilir, karsilastirma
// her esikte kucuktur ile yapilir.
const ilk = new Map();
for (const o of ham) { const a = `${o.abone_no}|${o.donem}`; if (!ilk.has(a)) ilk.set(a, o); }
export const UZUN = [...ilk.values()].map((o) => ({ ...o,
  basamak: o.tuketim_m3 < TARIFE[0] ? 1 : o.tuketim_m3 < TARIFE[1] ? 2
    : o.tuketim_m3 < TARIFE[2] ? 3 : 4 }));

export const grupla = (a, f) => {
  const m = new Map();
  for (const o of a) { const k = f(o); if (!m.has(k)) m.set(k, []); m.get(k).push(o); }
  return m;
};
export const ort = (a) => a.reduce((x, y) => x + y, 0) / a.length;
export const gen = (w) => (h) => h.map((v, j) => (j ? String(v).padStart(w[j])
  : String(v).padEnd(w[0]))).join("");

if (import.meta.url === `file://${process.argv[1]}`) {
  console.log(`model (tohum ${TOHUM}): giren ${UZUN.length} satir, ` +
    `${new Set(UZUN.map((o) => o.abone_no)).size} abone, 5 bolge, ` +
    `${DONEM.length} donem, ${TARIFE.length + 1} tarife basamagi`);
  const K = [
    ["G1 bolge", (o) => o.bolge, 5],
    ["G2 bolge x donem", (o) => `${o.bolge}|${o.donem}`, 15],
    ["G3 bolge x basamak x donem", (o) => `${o.bolge}|${o.basamak}|${o.donem}`, 60],
    ["G4 abone", (o) => o.abone_no, null],
  ];
  const y = gen([30, 9, 9, 10, 12, 10]);
  console.log("\n" + y(["gruplama karari", "giren", "cikan", "olasi goz", "gozde ort.",
    "bos goz"]));
  for (const [ad, f, olasi] of K) {
    const g = grupla(UZUN, f);
    console.log(y([ad, UZUN.length, g.size, olasi ?? "-",
      (UZUN.length / g.size).toFixed(1), olasi === null ? "-" : olasi - g.size]));
  }
  const g3 = grupla(UZUN, (o) => `${o.bolge}|${o.basamak}|${o.donem}`);
  console.log(`\ncapraz kirilimin ${60 - g3.size} gozu hic satir tasimiyor ve cikti ` +
    `tablosunda hic gorunmuyor; okuyan taraf "sifir" ile "veri yok" arasini ayiramaz`);
  const tek = [...grupla(UZUN, (o) => `${o.bolge}|${o.basamak}|${o.donem}`).values()]
    .filter((l) => l.length === 1).length;
  console.log(`ayni kirilimda ${tek} goz tek bir okumadan olusuyor: o gozun ` +
    `"ortalamasi" bir okumanin kendisidir`);
}
model (tohum 20260218): giren 3199 satir, 1260 abone, 5 bolge, 3 donem, 4 tarife basamagi

gruplama karari                   giren    cikan olasi goz  gozde ort.   bos goz
G1 bolge                           3199        5         5       639.8         0
G2 bolge x donem                   3199       15        15       213.3         0
G3 bolge x basamak x donem         3199       53        60        60.4         7
G4 abone                           3199     1260         -         2.5         -

capraz kirilimin 7 gozu hic satir tasimiyor ve cikti tablosunda hic gorunmuyor; okuyan taraf "sifir" ile "veri yok" arasini ayiramaz
ayni kirilimda 1 goz tek bir okumadan olusuyor: o gozun "ortalamasi" bir okumanin kendisidir

Dört karar da aynı 3.199 satırı okuyor ve dört farklı satır sayısı üretiyor. Çıkan satır sayısı hesaptan gelmiyor: G1 beş satır verir çünkü beş bölge vardır, G4 1.260 satır verir çünkü 1.260 abone vardır. Toplulaştırmanın kendisi tek bir satırın nasıl hesaplandığını belirler; kaç satır kalacağını gruplama alanı belirler.

Üçüncü satır bu dersin sessiz kaybını taşıyor. Bölge, tarife basamağı ve dönemin çaprazı 60 göz tanımlar ama çıktı 53 satırdır. Eksik 7 göz bir hata değil, o kombinasyonda hiç okuma bulunmamasıdır: örneğin belirli bir bölgede belirli bir dönemde en üst tarife basamağına giren bir okuma yoktur. Sorun, bu 7 gözün çıktıda hiç görünmemesidir. Çıktıyı okuyan biri 53 satır görür ve eksik olanın sıfır tüketimli bir göz mü, hiç ölçüm yapılmamış bir göz mü olduğunu ayırt edemez. Boş gözün sayılabilmesi için beklenen göz kümesinin ayrıca kurulması gerekir, tıpkı önceki dersin geniş biçiminde boş hücrelerin sayılabilir hale gelmesi gibi.

Son satır ölçeğin öteki ucunu gösteriyor: aynı kırılımda bir göz tek bir okumadan oluşuyor. O gözün “ortalaması” bir özet değil, tek bir okumanın kendisidir ve yanında bir grup varmış gibi raporlanır. Gruplama inceldikçe göz başına düşen satır 639,8’den 213,3’e, oradan 60,4’e ve en uçta 1’e iner; sayı özet olmaktan çıkıp gözlemin kendisi olur.

Özetin Sildiği Değişkenlik

// degisken.mjs — bes satirlik ozetin tasidigi ve tasimadigi bilgi. Ayni
// kumeden uc genel ortalama ve ozetten cevaplanamayan uc soru.
import { UZUN, grupla, ort, gen } from "./grupla.mjs";

const sapma = (a) => { const m = ort(a);
  return Math.sqrt(ort(a.map((x) => (x - m) ** 2))); };
const gB = grupla(UZUN, (o) => o.bolge);
const y = gen([10, 9, 11, 11, 9, 9, 11]);
console.log(y(["bolge", "okuma", "ortalama", "std sapma", "en kucuk", "en buyuk",
  "acikligi"]));
const ozet = [...gB].map(([k, l]) => {
  const v = l.map((o) => o.tuketim_m3);
  return { k, n: l.length, m: ort(v), s: sapma(v), a: Math.min(...v), b: Math.max(...v) };
}).sort((x, z) => z.m - x.m);
for (const s of ozet) console.log(y([s.k, s.n, s.m.toFixed(2), s.s.toFixed(2),
  s.a.toFixed(2), s.b.toFixed(2), (s.b - s.a).toFixed(2)]));

const tum = UZUN.map((o) => o.tuketim_m3);
const gH = grupla(UZUN, (o) => `${o.bolge}|${o.basamak}|${o.donem}`);
console.log(`\nayni kumeden uc genel ortalama:`);
console.log(`  ${UZUN.length} ham satirdan   ${ort(tum).toFixed(3)} m3`);
console.log(`  ${gB.size} bolge satirindan     ${ort(ozet.map((s) => s.m)).toFixed(3)} m3`);
console.log(`  ${gH.size} hucre satirindan   ` +
  `${ort([...gH.values()].map((l) => ort(l.map((o) => o.tuketim_m3)))).toFixed(3)} m3`);
console.log(`  fark ${(ort([...gH.values()].map((l) => ort(l.map((o) => o.tuketim_m3))))
  - ort(tum)).toFixed(3)} m3; her gruba esit agirlik verilince kucuk gruplar buyur`);

// Ozetten cevaplanamayan sorular: cevabi ham satirlardan ve bes satirlik
// ozetten ayri ayri okuyup yan yana koyalim.
const ESIK_M3 = 40, PAY = 0.5;
const ustu = tum.filter((v) => v > ESIK_M3).length;
const ozetUstu = ozet.filter((s) => s.m > ESIK_M3).length;
let uzak = 0;
for (const [, l] of gB) { const m = ort(l.map((o) => o.tuketim_m3));
  for (const o of l) if (Math.abs(o.tuketim_m3 - m) > PAY * m) uzak++; }
const enUst = ozet[0], enAlt = ozet[ozet.length - 1];
const asagi = gB.get(enUst.k).filter((o) => o.tuketim_m3 < enAlt.m).length;
const yukari = gB.get(enAlt.k).filter((o) => o.tuketim_m3 > enUst.m).length;

const y2 = gen([44, 12, 12]);
console.log("\n" + y2(["soru", "ham satir", "bes satir"]));
console.log(y2([`kac okuma ${ESIK_M3} m3 ustunde`, ustu, ozetUstu]));
console.log(y2(["kac okuma kendi grup ortalamasindan uzak", uzak, "okunamaz"]));
console.log(y2([`${enUst.k} ile ${enAlt.k} kac okumada yer degistiriyor`,
  asagi + yukari, "okunamaz"]));
console.log(`\nozet ${enUst.k} ${enUst.m.toFixed(2)} > ${enAlt.k} ` +
  `${enAlt.m.toFixed(2)} diyor; ${enUst.k} bolgesinin ${asagi} okumasi ${enAlt.k} ` +
  `ortalamasinin altinda, ${enAlt.k} bolgesinin ${yukari} okumasi ${enUst.k} ortalamasinin ustunde`);
bolge         okuma   ortalama  std sapma en kucuk en buyuk   acikligi
dogu            557      24.67       9.19     0.00    51.90      51.90
merkez          600      22.40       9.02     0.00    52.47      52.47
kuzey           921      20.21       7.46     0.00    45.47      45.47
guney           645      16.60       6.08     0.00    37.56      37.56
bati            476      13.78       5.00     0.00    31.95      31.95

ayni kumeden uc genel ortalama:
  3199 ham satirdan   19.713 m3
  5 bolge satirindan     19.532 m3
  53 hucre satirindan   20.721 m3
  fark 1.008 m3; her gruba esit agirlik verilince kucuk gruplar buyur

soru                                           ham satir   bes satir
kac okuma 40 m3 ustunde                               58           0
kac okuma kendi grup ortalamasindan uzak             431    okunamaz
dogu ile bati kac okumada yer degistiriyor            50    okunamaz

ozet dogu 24.67 > bati 13.78 diyor; dogu bolgesinin 39 okumasi bati ortalamasinin altinda, bati bolgesinin 11 okumasi dogu ortalamasinin ustunde

İlk tablo beş satırın taşıdığından fazlasını gösteriyor, çünkü yanına standart sapma ve uç değerler eklendi. Bir özet satırı yalnız ortalamayı taşısaydı, doğu bölgesinin 24,67 m³’ü ile batı bölgesinin 13,78 m³’ü arasındaki 10,89 m³’lük fark, grup içindeki 51,90 ve 31,95 m³’lük açıklıkların yanında küçük kalır ve bu karşılaştırma hiç yapılamazdı.

Ortadaki blok aynı kümeden üç genel ortalama çıkarıyor. 3.199 ham satırdan 19,713 m³; beş bölge satırından 19,532 m³; 53 hücre satırından 20,721 m³. Üçü de doğru hesaplanmıştır ve aralarındaki fark bir ağırlık kararıdır: toplulaştırılmış satırlar yeniden toplulaştırıldığında 476 okumalı batı bölgesi ile 921 okumalı kuzey bölgesi eşit sayılır, aynı şekilde 60 okumalı bir hücre ile bir okumalı bir hücre eşit sayılır. Hücre düzeyinde yeniden toplulaştırmanın ham satırdan sapması 1,008 m³’tür, yani genel ortalamanın yüzde beşi. Bu, önceki kursta bir sayfa üzerinde ölçülmüş olan aynı tuzağın betik tarafındaki karşılığıdır ve burada satır sayılarıyla birlikte okunur: sapmanın kaynağı 53 ile 3.199 arasındaki farktır.

Son tablo kaybı doğrudan sayıyor. 58 okuma 40 m³’ün üstündedir ve bu eşik tarife basamaklarının en üstü olduğu için seçilmiştir; beş satırlık özete aynı soru sorulduğunda cevap sıfır çıkar, çünkü hiçbir bölge ortalaması 40 m³’ü aşmaz. Cevap yanlış değildir, sorulan soru artık başka bir sorudur ve bunu okuyan taraf göremez.

431 okuma kendi grup ortalamasından yüzde elliden fazla sapar; oran eşiği bölge ortalamaları 13,78 ile 24,67 m³ arasında değiştiği için mutlak bir metre küp eşiğine tercih edilmiştir. Beş satırlık özet bu sayıyı hiç taşımaz. Aynı şekilde 50 okuma iki uç bölge arasında yer değiştirir: doğu bölgesinin 39 okuması batı ortalamasının altında, batı bölgesinin 11 okuması doğu ortalamasının üstündedir. Özet “doğu batıdan yüksek” der ve bu doğrudur; taşımadığı şey, tek tek okumalara bakıldığında bu sıralamanın 50 kez tersine döndüğüdür.

Dersin satır hesabı böylece kapanır: 3.199 satır girdi, 5 satır çıktı, 3.194 satır özetin içinde eridi. Erime bir kayıp değildir — amacı budur — ama eriyenin ne olduğu yazılmazsa özet, arkasındaki kümenin yerine geçer.

Özet

  • Çıkan satır sayısını hesap değil gruplama alanı belirler: aynı 3.199 satır sırasıyla 5, 15, 53 ve 1.260 satıra iner.
  • Çapraz kırılımın 60 gözünden 7’si hiç satır taşımaz ve çıktıda hiç görünmez; okuyan taraf “sıfır” ile “veri yok” arasını ayıramaz. Bir göz tek bir okumadan oluşur ve özet olmaktan çıkar.
  • Toplulaştırılmış satırların yeniden toplulaştırılması her gruba eşit ağırlık verir: aynı kümeden 19,713, 19,532 ve 20,721 m³ olmak üzere üç genel ortalama çıkar.
  • Bir özet satırı grubun merkezini taşır, yayılımını taşımaz: 3.199 okumanın 431’i kendi grup ortalamasından yüzde elliden fazla sapar ve bu sayı beş satırdan okunamaz.
  • Beş satırlık özet “40 m³’ün üstünde kaç okuma var” sorusuna sıfır der, ham satırlarda cevap 58’dir; doğu ile batı bölgeleri 50 okumada yer değiştirir.

Sonraki Adım

Toplulaştırma satır sayısını düşürdü ama sütun kümesine dokunmadı: elde hâlâ ölçülmüş alanlar var, hesaplanmış alanlar yok. Çözümlemenin sorduğu sorular çoğunlukla ölçülen değeri değil, ondan türetilen bir büyüklüğü ister — kişi başına tüketim, günlük ortalama, dönemler arası değişim oranı. Türetme yeni satır üretmez, bu yüzden zararsız görünür. Zararı başka yerde çıkar: bölen sıfır olduğunda ya da girdilerden biri eksik olduğunda türetilmiş değer tanımsız kalır ve o satır sonraki adımda sessizce elenir. Sonraki ders türetmenin kaç satırda tanımsız kaldığını sayar ve bu satırların düşmesinin sonucu ne kadar oynattığını ölçer.

İ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