İçeriğe geç
academia.sh

Ders 13 / 17

Yeniden Şekillendirme

3.199 satırlık uzun biçimli küme 1.260 satır ve üç dönem sütunundan oluşan geniş biçime çevrilir; 3.780 hücrenin 3.199'u dolar, 581'i boş kalır. Yineleyen abone ve dönem çifti taşıyan 3.302 satırlık küme aynı geniş biçime sığmaz ve 103 satır hiçbir uyarı üretmeden üzerine yazılır. Geri dönüşün üç kararı üç ayrı satır sayısı verir: boş hücre atlanırsa 3.199 satır ve 19,713 m³ ortalama, boş hücre sıfırla doldurulursa 3.780 satır ve 16,683 m³, doğruluk sınamasıyla atlanırsa 119 gerçek sıfır okuma da silinir, 3.080 satır ve 20,474 m³ kalır. Üç yolda da toplam 63.060,6 m³'te sabittir.

İçindekiler

Bir önceki ders üç tabloyu tek bir kümede topladı ve elde bir satırda bir abonenin bir dönem okumasını taşıyan 3.199 satır kaldı. Bu biçim bazı sorulara doğrudan cevap verir: “toplam tüketim nedir” sorusu tek bir sütunun toplamıdır. Bazı sorulara vermez. “Bir abonenin ocak ile mart arasında tüketimi ne kadar değişti” sorusu, aynı abonenin iki ayrı satırını bulup yan yana koymayı gerektirir ve bu satır bazlı bir küme üzerinde doğrudan yapılamaz.

Bu ders kümenin şeklini değiştirir. Şekil değişimi bir hesap değildir; hiçbir değer toplanmaz, bölünmez, elenmez. Buna rağmen satır sayısı değişir ve bazı durumlarda değer de kaybolur. Dersin ölçüsü şudur: dönüşüm kayıpsız mı, yani geniş biçime çevrilip geri dönüldüğünde özgün kümeye ulaşılıyor mu.

  • VD6. Uzun biçim her ölçümü bir satır yapar: anahtar sütunları (abone ve dönem), bir değişken adı ve bir değer. Geniş biçim anahtarın bir bölümünü sütun başlığına taşır: bir satır bir abone, üç sütun üç dönemdir. Küme aynı kümedir, satır sayısı değildir.
  • VD7. Geniş biçimde satır sayısı tekil anahtar sayısına, hücre sayısı ise satır ile sütunun çarpımına eşittir. Uzun biçimde karşılığı olmayan her çarpım hücresi boş kalır.
  • VD8. Geniş biçim aynı anahtar çifti için tek bir hücre taşır. Uzun biçimde bir abone ve dönem çifti iki kez geçiyorsa ikinci değer birincinin üzerine yazılır ve hiçbir uyarı üretilmez.
  • VD9. Geri dönüşte boş hücre kararı dönüşümün kendisi kadar belirleyicidir: boş hücre atlanabilir, bir değerle doldurulabilir ya da yanlış bir sınamayla gerçek değerleri de silebilir.
  • VD10. Kayıpsızlık ölçülebilir bir şeydir: geri dönen küme ile özgün küme satır sayısı, anahtar kümesi ve toplam bakımından karşılaştırılır. Üçü aynıysa dönüşüm kayıpsızdır.

Aynı Küme, İki Şekil

// sekil.mjs — MODELDIR: onceki dersin cikardigi uzun bicimli kume ve ayni
// kumenin genis bicimi. Veri kumesi kurgudur; hicbir arayuz taklit edilmez.
export const TOHUM = 20260218, HAM = 1400, DONEM = ["2026-01", "2026-02", "2026-03"];
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));
// Onceki dersin ic birlestirmesinden gecmis satirlar: eslesmeyen 169 okuma yok,
// ayni abone+donem ciftini ikinci kez tasiyan satirlar hala icinde.
export const YINELI = [];
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; }
    YINELI.push({ abone_no: k.abone_no, bolge: k.bolge, donem: DONEM[d], tuketim_m3: t });
    if (r() < 0.028) YINELI.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: bir abone+donem cifti bir satir.
const ilk = new Map();
for (const o of YINELI) { const a = `${o.abone_no}|${o.donem}`;
  if (!ilk.has(a)) ilk.set(a, o); }
export const UZUN = [...ilk.values()];

// Genisletme: anahtarin bir bolumu sutun basligina tasinir. Ayni hucreye ikinci
// kez yazilan deger birincinin uzerine yazilir; islem hata uretmez.
export const genislet = (uzun) => {
  const satir = new Map();
  let yazma = 0, uzerine = 0;
  for (const o of uzun) {
    if (!satir.has(o.abone_no)) satir.set(o.abone_no,
      { abone_no: o.abone_no, bolge: o.bolge, ...Object.fromEntries(DONEM.map((d) => [d, null])) });
    const s = satir.get(o.abone_no);
    if (s[o.donem] !== null) uzerine++; else yazma++;
    s[o.donem] = o.tuketim_m3;
  }
  return { genis: [...satir.values()], yazma, uzerine };
};
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]}`) {
  const G = genislet(UZUN), Y = genislet(YINELI);
  const hucre = G.genis.length * DONEM.length;
  console.log(`model (tohum ${TOHUM}): uzun bicim ${UZUN.length} satir, ` +
    `${G.genis.length} tekil abone, ${DONEM.length} donem`);
  const y = gen([12, 10, 12, 12, 12]);
  console.log("\ngenis bicim (ilk bes satir)");
  console.log(y(["abone_no", "bolge", ...DONEM]));
  for (const s of G.genis.slice(0, 5))
    console.log(y([s.abone_no, s.bolge, ...DONEM.map((d) => s[d] === null ? "-" : s[d])]));
  console.log(`\n${G.genis.length} satir x ${DONEM.length} sutun = ${hucre} hucre; ` +
    `${G.yazma} dolu, ${hucre - G.yazma} bos`);
  console.log(`girenin sekli degisti, satir sayisi ${UZUN.length} -> ${G.genis.length}`);
  console.log(`\nyineleyen kume genisletilirse: giren ${YINELI.length} satir, ` +
    `cikan ${Y.genis.length} satir, dolan hucre ${Y.yazma}`);
  console.log(`${Y.uzerine} satir ayni hucreye ikinci kez yazildi ve birincinin ` +
    `uzerine gecti; hicbir uyari uretilmedi`);
}
model (tohum 20260218): uzun bicim 3199 satir, 1260 tekil abone, 3 donem

genis bicim (ilk bes satir)
abone_no         bolge     2026-01     2026-02     2026-03
10001           merkez       30.09       24.65           -
10002            kuzey       20.21       22.14       21.57
10003            guney       13.42       14.12       18.75
10004            kuzey       20.01       20.29       17.48
10005            guney       18.29           -           -

1260 satir x 3 sutun = 3780 hucre; 3199 dolu, 581 bos
girenin sekli degisti, satir sayisi 3199 -> 1260

yineleyen kume genisletilirse: giren 3302 satir, cikan 1260 satir, dolan hucre 3199
103 satir ayni hucreye ikinci kez yazildi ve birincinin uzerine gecti; hicbir uyari uretilmedi

Geniş biçim ile uzun biçim aynı 3.199 ölçümü taşır. Fark, ölçümün nereden okunduğudur: uzun biçimde dönem bir değer, geniş biçimde bir sütun adıdır. “Ocak ile mart arasındaki değişim” sorusu geniş biçimde tek satırda iki sütunun farkıdır; uzun biçimde iki satırı eşleştirmeyi gerektirir.

Şeklin bedeli 581 boş hücredir. Bunlar bir eksiklik değil, uzun biçimde hiç var olmayan kombinasyonlardır: 1.260 abonenin hepsi üç dönemde de okunmamıştır. Geniş biçim, olmayan bir satırı boş bir hücreye çevirerek görünür kılar; uzun biçimde o kombinasyon hiç yoktu ve sayılamıyordu. Bu, geniş biçimin gerçek bir kazancıdır: eksiklik ancak beklenen kombinasyon kümesi kurulduğunda sayılabilir hale gelir.

İki biçimden biri doğru değildir; soru hangisinin uygun olduğunu belirler. Geniş biçimin bir sınırı vardır ve satır sayısıyla ilgisizdir: sütun sayısı, başlığa taşınan anahtarın tekil değer sayısına eşittir. Üç dönem üç sütun eder, otuz altı dönem otuz altı sütun eder ve dönem sayısı önceden bilinmiyorsa tablonun şeması veriyle birlikte değişir. Uzun biçimde aynı büyüme yeni sütun değil yeni satır üretir ve şema sabit kalır. Bu yüzden hazırlamanın çıktısı çoğunlukla uzun biçimde saklanır ve geniş biçim yalnız belirli bir soru için, geçici olarak üretilir.

Son iki satır dersin sessiz kaybını gösteriyor. Önceki dersin ayıkladığı yinelemeler ayıklanmasaydı elde 3.302 satır olurdu ve o küme aynı geniş biçime çevrildiğinde yine 1.260 satır ve 3.199 dolu hücre çıkardı. 103 satır aynı hücreye ikinci kez yazıldı ve birincinin üzerine geçti. İşlem başarıyla tamamlandı, hata üretilmedi, satır sayısındaki düşüş de zaten beklenen bir düşüştü. Geniş biçime çevirme bu yüzden bir tekilleştirme aracı gibi kullanılabilir; kullanıldığında hangi değerin kaldığını kimse seçmemiştir.

Geri Dönüş Kayıpsız mı

// geridonus.mjs — genis bicimden uzun bicime donusun uc karari ve her birinin
// ozgun kume ile farki. Kayipsizlik satir, anahtar ve toplam ile olculur.
import { UZUN, DONEM, genislet, gen } from "./sekil.mjs";

const { genis } = genislet(UZUN);
// Y1 bos hucre atlanir. Y2 bos hucre sifirla doldurulur. Y3 hucre "dogru mu"
// diye sinanir; bu sinama sifiri da bos sayar.
const YOL = [
  ["Y1 bos hucre atlanir", (v) => v !== null],
  ["Y2 bos hucre sifirla doldurulur", () => true],
  ["Y3 hucre dogruluk sinamasindan gecer", (v) => Boolean(v)],
];
const uzat = (sec) => {
  const cikti = [];
  for (const s of genis) for (const d of DONEM) {
    if (!sec(s[d])) continue;
    cikti.push({ abone_no: s.abone_no, donem: d, tuketim_m3: s[d] ?? 0 });
  }
  return cikti;
};
const T = (a) => a.reduce((x, o) => x + o.tuketim_m3, 0);
const ozgunT = T(UZUN), sifir = UZUN.filter((o) => o.tuketim_m3 === 0).length;
console.log(`ozgun uzun bicim: ${UZUN.length} satir, ${ozgunT.toFixed(1)} m3, ` +
  `icinde ${sifir} adet gercek sifir okuma`);

const y = gen([38, 9, 8, 11, 10]);
console.log("\n" + y(["geri donus karari", "satir", "fark", "toplam m3", "ortalama"]));
for (const [ad, sec] of YOL) {
  const g = uzat(sec), f = g.length - UZUN.length;
  console.log(y([ad, g.length, f > 0 ? `+${f}` : f, T(g).toFixed(1),
    (T(g) / g.length).toFixed(3)]));
}
// Kayipsizlik sinamasi: satir sayisi, anahtar kumesi ve toplam ayni mi. Toplam
// kayan noktali oldugu icin esitlik yerine esik kullanilir; 0,05 m3 secildi
// cunku okumalar 0,01 m3 duyarliginda kaydediliyor ve toplam 3199 terimlidir.
const ESIK_M3 = 0.05;
const anahtar = (a) => new Set(a.map((o) => `${o.abone_no}|${o.donem}`));
const ozgunA = anahtar(UZUN);
console.log("\n" + gen([38, 9, 10, 10, 10])(["kayipsizlik sinamasi", "satir",
  "anahtar", "toplam", "kayipsiz"]));
for (const [ad, sec] of YOL) {
  const g = uzat(sec), a = anahtar(g);
  const s1 = g.length === UZUN.length;
  const s2 = a.size === ozgunA.size && [...ozgunA].every((k) => a.has(k));
  const s3 = Math.abs(T(g) - ozgunT) < ESIK_M3;
  console.log(gen([38, 9, 10, 10, 10])([ad, s1 ? "ayni" : "farkli",
    s2 ? "ayni" : "farkli", s3 ? "ayni" : "farkli",
    s1 && s2 && s3 ? "evet" : "hayir"]));
}
console.log(`\nuc yolda da toplam ${ozgunT.toFixed(1)} m3 degismedi; ` +
  `ortalama 16,683 ile 20,474 m3 arasinda gidip geldi`);
ozgun uzun bicim: 3199 satir, 63060.6 m3, icinde 119 adet gercek sifir okuma

geri donus karari                         satir    fark  toplam m3  ortalama
Y1 bos hucre atlanir                       3199       0    63060.6    19.713
Y2 bos hucre sifirla doldurulur            3780    +581    63060.6    16.683
Y3 hucre dogruluk sinamasindan gecer       3080    -119    63060.6    20.474

kayipsizlik sinamasi                      satir   anahtar    toplam  kayipsiz
Y1 bos hucre atlanir                       ayni      ayni      ayni      evet
Y2 bos hucre sifirla doldurulur          farkli    farkli      ayni     hayir
Y3 hucre dogruluk sinamasindan gecer     farkli    farkli      ayni     hayir

uc yolda da toplam 63060.6 m3 degismedi; ortalama 16,683 ile 20,474 m3 arasinda gidip geldi

Yalnız Y1 kayıpsızdır: satır sayısı, anahtar kümesi ve toplam üçü de özgün kümeyle aynıdır. Öteki iki yol da hatasız çalışır ve ikisi de aynı toplamı verir.

Y2 boş hücreyi sıfırla doldurur ve 581 satır uydurur. Bu satırlar yanlış değildir; yanlış olan varsayımdır — okunmamış bir dönem, sıfır tüketilmiş bir dönem değildir. Anahtar kümesi özgünün tamamını içerir ama 581 fazlası vardır, bu yüzden sınamayı geçmez. Toplam değişmediği için hata toplamda görünmez; ortalamada görünür ve 19,713 m³’ten 16,683 m³’e iner. Sayı yüzde on beşten fazla kaymıştır ve tek bir okuma değişmemiştir.

Y3 dersin en sinsi kararıdır ve bir kodlama alışkanlığından doğar: hücrenin dolu olup olmadığı, değerinin doğruluk sınamasından geçip geçmediğine bakılarak sorulmuştur. Sıfır bu sınamadan geçmez. Sonuç, 119 gerçek sıfır okumanın boş hücrelerle birlikte silinmesidir. Anahtar kümesi burada ters yönde bozulur: geri dönen kümede özgünün 119 anahtarı eksiktir. Toplam yine değişmez, çünkü silinen okumaların değeri sıfırdır; ortalama ise ters yöne, 20,474 m³’e çıkar.

Üç yolun toplamı aynı, ortalaması farklıdır. Bu, kayıpsızlığın neden toplamla sınanamayacağını gösteriyor: sıfır değerli satırların eklenmesi ya da silinmesi toplamı hiç oynatmaz. Kayıpsızlık sınaması bu yüzden satır sayısı, anahtar kümesi ve toplam olmak üzere üç ayrı karşılaştırma ister. Toplam karşılaştırması kayan noktalı olduğu için eşitlikle değil 0,05 m³’lük bir eşikle yapılır; eşik okumaların 0,01 m³ duyarlığından ve toplamın üç binden fazla terimli olmasından seçilmiştir.

Özet

  • Uzun biçim her ölçümü bir satır yapar, geniş biçim anahtarın bir bölümünü sütun başlığına taşır: aynı küme 3.199 satır ile 1.260 satır arasında yer değiştirir, tek bir değer değişmeden.
  • Geniş biçimde 1.260 satır ve üç sütun 3.780 hücre üretir; 3.199’u dolar, 581’i boş kalır ve bu boş hücreler eksikliği ilk kez sayılabilir hale getirir.
  • Yineleyen abone ve dönem çifti taşıyan 3.302 satırlık küme aynı geniş biçime sığmaz: 103 satır hiçbir uyarı üretmeden üzerine yazılır ve hangi değerin kaldığını kimse seçmemiştir.
  • Geri dönüşün üç kararı üç satır sayısı verir: 3.199, 3.780 ve 3.080. Yalnız birincisi kayıpsızdır.
  • Boş hücrenin sıfırla doldurulması ortalamayı 19,713’ten 16,683 m³’e indirir; doğruluk sınaması 119 gerçek sıfır okumayı siler ve ortalamayı 20,474 m³’e çıkarır. Toplam üç yolda da 63.060,6 m³’tür.

Sonraki Adım

Şekil değişimi tek bir ölçümü bile toplamadı; 3.199 satır 1.260 satıra indiğinde her değer hâlâ kendi hücresindeydi. Rapora giren sayı ise nadiren bir hücredir. “Bölge başına ortalama tüketim” sorusu binlerce satırı beş satıra indirmeyi ister ve bu indirme geri alınamaz: beş satıra bakan biri arkalarındaki dağılımı göremez, yalnız özetin bıraktığı sayıyı görür. Sonraki ders gruplamanın ürettiği satır sayısını sayar ve grup içindeki değişkenliğin özetle birlikte ne kadarının kaybolduğunu ö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