Ders 01 / 11
Çalışma Sayfası Yapısı
Tek bir tutar formülü 60 satıra kopyalanıyor ve başvuru kararı değişince toplam 13 427,16 ücret biriminden 3 354,98'e düşüyor: göreli başvuru 59 hücreye yanlış yayılıyor, bunların 52'si sıfır, 7'si bir tutar gibi okunan yanlış sayı. Gömülü sabitle yazılan üçüncü sürüm aynı toplamı veriyor ama birim ücret 8,4'ten 9,1'e çıktığında 60 hücre yerine 0 hücre peşinden geliyor. Sayfadaki 8 parametrenin 6'sı hiçbir formüle girmiyor.
İçindekiler
Veri Analitiğine Giriş kursu şu soruyla kapandı: dokuz derste kararların sayıyı oynattığı gösterildi, ama bütün kararlar elle alındı ve hiçbiri yazılı bir yerde durmuyor; aynı hesabı ikinci kez yapan biri aynı sayıyı bulacak mı. Elektronik tablo bu soruya verilen ilk cevaptır. Hesap artık bir kişinin kafasında değil, bir hücrede durur ve hücre yeniden hesaplanabilir.
Bu kurs cevabın ne kadarını tuttuğunu ölçer. Ölçü iki parçalıdır ve her derste iki sayı yan yana durur. Birincisi önceki kurstan sürer: sayı ve onu üreten karar. İkincisi bu kursun kendi ölçüsüdür: kararın kurtarılabilirliği — tabloya bakan ikinci kişi o kararı kaç adımda geri okuyabiliyor, kaç karar hiç geri okunamıyor. Bu ders ikisini de bir tek formül üzerinde kurar.
- TT1. Çalışma sayfası burada bir modeldir: hücreler bir eşleme, formüller kısa bir metin, aralıklar bir dilim işlevidir. Model bir uygulamayı taklit etmez; kopyalama kuralı da değerlendirme kuralı da aşağıda açıkça yazılıdır.
- TT2. Veri kümesi Veri Analitiğine Giriş kursunun bölgesel ölçüm ağıdır: abone kayıtları, sayaç okumaları, saha ziyaretleri, tarife basamakları. Ağ da kayıtlar da kurgudur; buradaki sayfa 60 abonelik bir saha listesidir ve kendi tohumuyla üretilir.
- TT3. Hücre adı sütun harfi ile satır numarasıdır. Bir başvuru göreli ise kopyalandığı
kadar kayar, mutlak ise (
$işaretiyle) kaymaz. Karma başvuruda yalnız işaretlenen parça sabit kalır. - TT4. Boş hücre bu modelde sayısal bağlamda
0okunur. Bu bir karardır ve sonucu doğrudan etkiler; sonraki ders boş hücrenin sayılıp sayılmaması sorusunu ayrıca ölçer. - TT5. Bir karar geri okunabilir sayılır: ikinci kişi hücrenin formül metnini okuyarak kararın nerede tutulduğunu ve değerini bulabiliyorsa. Formülün içine gömülmüş sabit sayı geri okunabilir değildir — sayı görülür, ama nereden geldiği görünmez.
- TT6. Ücret bir ücret birimidir; ölçek modelin ölçeğidir.
Sayfa, Hücre, Aralık
Aşağıdaki blok modeli kurar. Üç parçası vardır: hücre eşlemesi, kaydir işlevinin uyguladığı
kopyalama kuralı ve deger işlevinin uyguladığı değerlendirme. Değerlendirme özyinelemelidir —
bir formül başka bir formüle başvurabilir.
// tablo.mjs — elektronik tablo MODELI: hucreler bir esleme, formul bir metin, aralik bir // dilim islevidir. Sayfa da kayitlar da kurgudur; hicbir uygulamanin davranisi taklit edilmez. export const TOHUM = 20260602, SATIR = 60; const uretec = (t) => { let s = t >>> 0; return () => (s = (s * 1664525 + 1013904223) >>> 0) / 4294967296; }; const BOLGE = ["kuzey", "guney", "dogu", "bati", "merkez"]; export const REF = /(\$?)([A-Z])(\$?)(\d+)/g; const coz = (a) => ({ s: a.charCodeAt(a[0] === "$" ? 1 : 0) - 65, r: +a.replace(/\D/g, "") }); const adi = (s, r) => String.fromCharCode(65 + s) + r; // Kopyalama kurali: gorel basvuru kopyalandigi kadar kayar, mutlak basvuru ($) kaymaz. export const kaydir = (f, dS, dR) => f.replace(REF, (_, a, s, b, r) => (a ? "$" + s : String.fromCharCode(s.charCodeAt(0) + dS)) + (b ? "$" + r : String(+r + dR))); const ISLEV = { toplam: (d) => d.reduce((a, b) => a + b, 0) }; const ARALIK = /(\$?[A-Z]\$?\d+):(\$?[A-Z]\$?\d+)/g; const ac = (a, b) => { const x = coz(a), y = coz(b), l = []; for (let s = x.s; s <= y.s; s++) for (let r = x.r; r <= y.r; r++) l.push(adi(s, r)); return l; }; export function deger(H, ad) { const v = H[ad]; if (v === undefined) return 0; // bos hucre bu modelde 0 okunur if (typeof v !== "string" || v[0] !== "=") return v; const ifade = v.slice(1) .replace(ARALIK, (_, a, b) => "[" + ac(a, b).map((c) => deger(H, c)).join(",") + "]") .replace(REF, (m) => String(deger(H, m.replace(/\$/g, "")))); return Function(...Object.keys(ISLEV), `return (${ifade});`)(...Object.values(ISLEV)); } export function sayfa() { const r = uretec(TOHUM), H = {}; H.A1 = "abone"; H.B1 = "bolge"; H.C1 = "tuketim"; H.E1 = "tutar"; for (let i = 0; i < SATIR; i++) { const s = i + 2; H["A" + s] = "AB-" + String(1041 + i * 7).padStart(4, "0"); H["B" + s] = BOLGE[Math.floor(r() * 5)]; H["C" + s] = Math.round((2 + r() * r() * 78) * 10) / 10; } // Parametre blogu: solda etiket, sagda deger. Tarife basamaklari 10/25/40 m3'tur. H.G1 = "parametre"; H.H1 = "deger"; ["birim ucret", "sabit bedel", "sayac bakim", "kayip payi", "basamak 1", "basamak 2", "basamak 3", "indirim"].forEach((e, j) => { H["G" + (j + 2)] = e; }); [8.4, 25, 3.5, 1.2, 10, 25, 40, 0.9].forEach((v, j) => { H["H" + (j + 2)] = v; }); return H; } if (import.meta.url === `file://${process.argv[1]}`) { const H = sayfa(); const dolu = Object.keys(H).length; console.log(`tohum ${TOHUM}: ${SATIR} abone satiri, ${dolu} dolu hucre`); console.log("parametre blogu H2:H9 = " + ac("H2", "H9").map((c) => H[c]).join(", ") + "\n"); const g = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j]) : String(v).padEnd(B[0]))).join(""); const y = g([8, 10, 10]); console.log(y(["hucre", "abone", "tuketim"])); for (const s of [2, 3, 4, 60, 61]) console.log(y(["C" + s, H["A" + s], H["C" + s].toFixed(1)])); console.log(`\nC2:C61 toplami ${deger({ ...H, X1: "=toplam(C2:C61)" }, "X1").toFixed(1)} m3`); console.log("kaydir('=C2*$H$2+H3', 0, 1) -> " + kaydir("=C2*$H$2+H3", 0, 1)); }
tohum 20260602: 60 abone satiri, 202 dolu hucre
parametre blogu H2:H9 = 8.4, 25, 3.5, 1.2, 10, 25, 40, 0.9
hucre abone tuketim
C2 AB-1041 9.8
C3 AB-1048 71.6
C4 AB-1055 6.7
C60 AB-1447 3.0
C61 AB-1454 21.2
C2:C61 toplami 1419.9 m3
kaydir('=C2*$H$2+H3', 0, 1) -> =C3*$H$2+H4
Son satır dersin tamamını içeriyor. Aynı formül bir satır aşağı kopyalandığında $H$2 yerinde
kaldı, H3 ise H4 oldu. Kopyalama bir metin işlemidir: hücrenin içindeki formül aynı kalmaz,
kaydırılarak yazılır. Hangi başvurunun kayacağına yazan kişi karar verir ve bu karar tek bir
işaretle verilir.
Aynı Hesap, Üç Başvuru Kararı
Hesap tektir: tutar, tüketimin birim ücretle çarpımı artı sabit bedel. Üç yazım da savunulabilir görünür. Birincisi parametrelere mutlak başvurur, ikincisi göreli başvurur, üçüncüsü sayıları formülün içine yazar.
// kopyala.mjs — ayni hesap uc basvuru karariyla yazilip 60 satira kopyalanir. import { sayfa, deger, kaydir, SATIR } from "./tablo.mjs"; const KARAR = [ { ad: "A: mutlak ($H$2, $H$3)", f: "=C2*$H$2+$H$3" }, { ad: "B: gorel (H2, H3)", f: "=C2*H2+H3" }, { ad: "C: sabit gomulu", f: "=C2*8.4+25" }, ]; // Bir formul E2'ye yazilip E61'e kadar kopyalanir: her kopyada satir farki kadar kaydirilir. const doldur = (H, f) => { const K = { ...H }; for (let i = 0; i < SATIR; i++) K["E" + (i + 2)] = kaydir(f, 0, i); return K; }; const sutun = (K) => Array.from({ length: SATIR }, (_, i) => deger(K, "E" + (i + 2))); const g = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j]) : String(v).padEnd(B[0]))).join(""); const H = sayfa(); const D = KARAR.map((k) => sutun(doldur(H, k.f))); const y = g([8, 10, 12, 12, 12]); console.log(y(["hucre", "tuketim", "A tutar", "B tutar", "C tutar"])); for (const s of [2, 3, 5, 9, 10, 30, 61]) { const i = s - 2; console.log(y(["E" + s, H["C" + s].toFixed(1), D[0][i].toFixed(2), D[1][i].toFixed(2), D[2][i].toFixed(2)])); } const t = (d) => d.reduce((a, b) => a + b, 0); // Kayan noktali karsilastirma esikle yapilir: tutarlar kurus altinda ayirt edilmez, // bu yuzden iki deger 0,005 ucret biriminden yakinsa "ayni" sayilir. const ESIK = 0.005; const ayni = (a, b) => Math.abs(a - b) < ESIK; const z = g([26, 12, 8, 10, 8]); console.log("\n" + z(["karar", "toplam", "yanlis", "sifir", "gorunur"])); KARAR.forEach((k, a) => { const yanlis = D[a].filter((v, i) => !ayni(v, D[0][i])).length; const sifir = D[a].filter((v) => ayni(v, 0)).length; console.log(z([k.ad, t(D[a]).toFixed(2), yanlis, sifir, yanlis - sifir])); }); console.log(`\nE2'ye tek formul yazildi, ${SATIR - 1} hucreye kopyalandi.`);
hucre tuketim A tutar B tutar C tutar E2 9.8 107.32 107.32 107.32 E3 71.6 626.44 1793.50 626.44 E5 26.8 250.12 42.16 250.12 E9 5.5 71.20 4.95 71.20 E10 49.1 437.44 0.00 437.44 E30 25.4 238.36 0.00 238.36 E61 21.2 203.08 0.00 203.08 karar toplam yanlis sifir gorunur A: mutlak ($H$2, $H$3) 13427.16 0 0 0 B: gorel (H2, H3) 3354.98 59 52 7 C: sabit gomulu 13427.16 0 0 0 E2'ye tek formul yazildi, 59 hucreye kopyalandi.
Rapor edilecek sayı 13 427,16 ücret birimidir. B kararı aynı hesaptan 3 354,98 üretti; fark 10 072,18, yani doğru toplamın dörtte üçü. Tek işaret farkı bu kadar oynattı.
Yayılım sütunları daha önemli bir şey yazıyor. Yazılan formül tektir; yanlış olan da tek bir
hücredir. Ama kopyalama o hücreyi 59 hücreye çoğalttı ve 59’unun hepsi yanlış değer üretti. Bunun
52’si sıfır — göze çarpar. Kalan 7’si sıfır değil: E5 hücresinde 250,12 yerine 42,16 yazıyor,
çünkü kayan başvuru tüketimi birim ücretle değil kayıp payıyla çarptı ve üstüne sabit bedel yerine
birinci tarife basamağının sınırını ekledi. 42,16 düşük tüketimli
bir abonenin faturası gibi okunur ve komşu satırlardan ayırt edilmez. Bir hatanın görünürlüğü
büyüklüğüyle değil, benzediği şeyle ölçülür.
C kararı A ile aynı toplamı verdi: 13 427,16. İki sütun hücre hücre eşit. Bir sonuç karşılaştırması bu iki yazımı ayıramaz.
Parametre Değişince Kim Peşinden Gelir
Ayıran şey sonuç değil, sayfanın değişime nasıl tepki verdiğidir. Birim ücret 8,4’ten 9,1’e çıkarılır ve tek bir hücre güncellenir.
// karar.mjs — parametre degisince kac hucre pesinden gelir, ve sayfadan kac karar geri okunur. import { sayfa, deger, kaydir, REF, SATIR } from "./tablo.mjs"; const FORMUL = { A: "=C2*$H$2+$H$3", B: "=C2*H2+H3", C: "=C2*8.4+25" }; const doldur = (H, f) => { const K = { ...H }; for (let i = 0; i < SATIR; i++) K["E" + (i + 2)] = kaydir(f, 0, i); K.E62 = "=toplam(E2:E61)"; return K; }; const g = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j]) : String(v).padEnd(B[0]))).join(""); const H = sayfa(), ZAM = { ...H, H2: 9.1 }; // birim ucret 8,4 -> 9,1 const y = g([6, 12, 12, 10, 10]); console.log(y(["karar", "toplam", "zam sonrasi", "fark", "pesinden"])); for (const [ad, f] of Object.entries(FORMUL)) { const K = doldur(H, f), Z = doldur(ZAM, f); const once = Array.from({ length: SATIR }, (_, i) => deger(K, "E" + (i + 2))); const sonra = Array.from({ length: SATIR }, (_, i) => deger(Z, "E" + (i + 2))); // Esik 0,005 ucret birimidir: bunun altindaki fark yuvarlamayla ayirt edilemez. const oynayan = once.filter((v, i) => Math.abs(v - sonra[i]) >= 0.005).length; console.log(y([ad, deger(K, "E62").toFixed(2), deger(Z, "E62").toFixed(2), (deger(Z, "E62") - deger(K, "E62")).toFixed(2), oynayan])); } // Sayfa taramasi: her formul metninden basvurular ve gomulu sabitler cikarilir. const tara = (K) => { const formuller = Object.entries(K).filter(([, v]) => typeof v === "string" && v[0] === "="); const basvurulan = new Set(), sabit = new Map(); for (const [, v] of formuller) { for (const m of v.matchAll(REF)) basvurulan.add(m[0].replace(/\$/g, "")); for (const s of v.replace(REF, "").match(/\d+(\.\d+)?/g) ?? []) sabit.set(s, (sabit.get(s) ?? 0) + 1); } const param = Array.from({ length: 8 }, (_, j) => "H" + (j + 2)); return { formul: formuller.length, kullanilan: param.filter((c) => basvurulan.has(c)), olu: param.filter((c) => !basvurulan.has(c)), sabit }; }; const z = g([6, 8, 28, 5, 16]); console.log("\n" + z(["karar", "formul", "kullanilan", "olu", "gomulu sabit"])); for (const [ad, f] of Object.entries(FORMUL)) { const t = tara(doldur(H, f)); console.log(z([ad, t.formul, t.kullanilan.join(","), t.olu.length, [...t.sabit].map(([s, n]) => `${s}x${n}`).join(" ")])); } const t = tara(doldur(H, FORMUL.A)); console.log(`\nParametre blogunda 8 deger var, formuller ${t.kullanilan.length} tanesine ` + `basvuruyor; ${t.olu.length} tanesi (${t.olu.join(", ")}) sayfada duruyor ama hicbir ` + `hesaba girmiyor.`);
karar toplam zam sonrasi fark pesinden A 13427.16 14421.09 993.93 60 B 3354.98 3361.84 6.86 1 C 13427.16 13427.16 0.00 0 karar formul kullanilan olu gomulu sabit A 61 H2,H3 6 B 61 H2,H3,H4,H5,H6,H7,H8,H9 0 C 61 8 8.4x60 25x60 Parametre blogunda 8 deger var, formuller 2 tanesine basvuruyor; 6 tanesi (H4, H5, H6, H7, H8, H9) sayfada duruyor ama hicbir hesaba girmiyor.
Bu dersin ikinci sayısı son sütundadır. A kararında bir hücrenin değişmesi 60 hücreyi oynattı; C kararında 0 hücreyi. C sayfası zam sonrası da 13 427,16 gösteriyor ve bu sayı artık yanlıştır — ama sayfada hiçbir işaret yoktur, çünkü hiçbir şey değişmemiştir.
Tarama sütunları farkın nerede olduğunu yazıyor. A’da iki karar formül metninden geri okunur:
$H$2 yazan biri H2 hücresine gider, yanındaki G2 etiketini okur ve birim ücreti bulur. İki
adım. C’de aynı karar 60 ayrı hücrede 8,4 olarak tekrar eder; bir sayı görülür, kaynağı
görülmez. Birim ücret değişecekse 60 formülün hepsi tek tek okunmalıdır ve hangi 8,4’ün birim
ücret, hangisinin başka bir şey olduğu ancak tahmin edilebilir. Geri okuma adımı yoktur.
Son satır üçüncü bir şey söylüyor. Sayfada 8 parametre var, formüller yalnız 2’sine başvuruyor; tarife basamakları dahil 6 parametre hiçbir hesaba girmiyor. Bunlar sayfada bir zamanlar alınmış kararların kalıntısıdır. Bakan kişi hepsini kullanımda sanır. Sayfada duran bir sayı, kullanılan bir sayı değildir.
Kararın İki Ölçüsü
Bu ders iki sayı üretti ve ikisi de raporlanmadan tablo teslim edilemez. Birincisi tutar toplamıdır: 13 427,16 ücret birimi, başvuru kararı değişince 3 354,98. İkincisi kurtarılabilirliktir: A kararında zam 60 hücreyi buldu, C kararında 0 hücreyi; A’da parametre kararı iki adımda geri okunuyor, C’de hiç okunamıyor.
İkinci sayı olmadan birincisi eksiktir, çünkü aynı 13 427,16 iki farklı sayfadan çıktı ve o iki sayfa aynı sayfa değil. Kursun kuralı buradan başlar: elektronik tablo bir hesap aracıdır, bir kayıt aracı değildir; hücreye gömülü karar, yazılmamış karardır.
Özet
- Çalışma sayfası bir hücre eşlemesidir; formül bir metindir ve kopyalandığında olduğu gibi değil, kaydırılarak yazılır. Göreli başvuru kayar, mutlak başvuru kaymaz.
- Aynı hesap üç başvuru kararıyla yazıldığında toplam 13 427,16 ile 3 354,98 arasında oynadı; fark, doğru toplamın dörtte üçüdür.
- Tek bir yanlış başvuru kopyalanarak 59 hücreye yayıldı; 52’si sıfır verdiği için göze çarpar, 7’si bir tutar gibi okunur. Bir hatanın görünürlüğü büyüklüğüyle değil, benzediği şeyle ölçülür.
- Sonuç karşılaştırması iki yazımı ayırmaz: gömülü sabitle yazılan sayfa aynı toplamı verir, ama birim ücret değiştiğinde 60 hücre yerine 0 hücre peşinden gelir.
- Kararın kurtarılabilirliği adım sayısıyla ölçülür: mutlak başvuruda iki adım, gömülü sabitte hiç. Sayfadaki 8 parametrenin 6’sı hiçbir formüle girmiyor ve bakan kişi bunu göremiyor.
Sonraki Adım
Bu ders bir hesabın hangi hücrelere yayıldığını saydı, ama hesabın hangi hücreleri saydığını
sormadı. toplam(E2:E61) yazıldığında aralıkta 60 hücre var; sayılan kaç tanesi. Sayaç
okumalarının bir bölümü boştur, bir bölümü sıfırdır, bir bölümü sayı gibi görünen bir metindir ve
üçü hücre içinde birbirine benzer. Sonraki ders aynı sütuna üç sayma işlevi uygular ve üç farklı
sonuç basar; ardından aynı sütunun ortalamasının paydasının hangi karara bağlı olduğunu ölçer.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.