Ders 17 / 17
Yeniden Üretilebilir Hazırlama
Kursun on yedi hazırlama adımı veri olarak yazılır: 39 karar, üç konuya 13'er kalem. Adımların ölçtüğü sessiz kayıp toplamı 4.614 kayıttır ve bunun yalnız 69'u benimsenen hatta gerçekleşmiştir; kalan 4.545 kayıt seçilmeyen yaygın kararın ölçülmüş bedelidir. Üç adım parametresini betikten değil koşum ortamından alır ve aynı veriyle iki koşum üçünde de farklı sonuç verir; hattın 17 adımının 14'ü yeniden üretilebilirken değerler betiğe yazılınca 17'si yeniden üretilebilir olur. Kararın geri okunabilirliği hücrelerde 32'de 7 (yüzde 22) iken betikte defter tutulmadan 39'da 36, koşum defteriyle 39'da 39'a çıkar.
İçindekiler
On yedi adımda küme hazırlandı ve her adımda giren, çıkan ve kaybolan satır sayıldı — ama bu sayımlar o dersin içinde kaldı, hiçbiri bir yerde toplu durmuyor. Aynı kümeyi ikinci kez hazırlayan biri hangi eşiğin seçildiğini, hangi sıralamanın kullanıldığını ya da hangi tohumla örnek çekildiğini bulamaz.
Elektronik Tablolarla Analiz kursu bu soruyla kapanmıştı: otuz iki kararın yalnız yedisi geri okunabiliyordu, çünkü kararlar hücrelere gömülüydü. Betik yazmak bunun cevabı gibi görünür ve kısmen öyledir. Bu ders betiğin nerede yetmediğini ölçer: kaç adım aynı veriden aynı sonucu veriyor ve kaç karar koşumdan sonra okunabiliyor.
- VD25. Bir hazırlama hattı, adımların verisi yazıldığında belgelenmiş olur: her adımın adı, kararları ve satır hesabı. Betiğin kendisi bu kaydın yerine geçmez.
- VD26. Bir adım, sonucunu belirleyen bütün değerler betikte yazılıysa yeniden üretilebilir. Değerlerden biri koşum ortamından geliyorsa aynı betik aynı veriden başka bir sonuç çıkarır ve fark hiçbir yerde görünmez.
Hattı Veri Olarak Yazmak
// hat.mjs — MODELDIR: kursun on yedi hazirlama adimi veri olarak yaziliyor. // "s" alani o dersin olctugu sessiz kayiptir — uyari uretmeden dusen ya da // bozulan kayit — ve kendi dersinden okundu. "p" adimin kararlaridir; degeri // "ortam" olan kararlar betikte yazili degildir, kosum aninda disaridan gelir. export const HAT = [ { n: 1, k: "toplama", ad: "dosya bicimleri", s: 142, p: { ayrac: ";", tirnak: "korunur", kodlama: "utf-8" } }, { n: 2, k: "toplama", ad: "veritabanindan cekme", s: 766, p: { birim: "abone-donem", birlestirme: "tekil anahtar" } }, { n: 3, k: "toplama", ad: "arayuzlerden toplama", s: 512, p: { sayfalama: "imlec", kapsam: "tum donemler", hiz: "sinira uyan sira" } }, { n: 4, k: "toplama", ad: "yapisal ayristirma", s: 1877, p: { secici: "anlamsal", denetim: "kaynak toplami" } }, { n: 5, k: "toplama", ad: "ornekleme", s: 0, p: { yontem: "tabakali", boy: 200, tohum: "ortam" } }, { n: 6, k: "temizleme", ad: "eksik degerler", s: 100, p: { eksik: "bos + bosluk + yok", karar: "doldur" } }, { n: 7, k: "temizleme", ad: "yinelenen kayitlar", s: 0, p: { anahtar: "kirpilmis sayac kodu", olcut: "kesin eslesme" } }, { n: 8, k: "temizleme", ad: "tip donusumleri", s: 465, p: { sayi: "bicim once taninir", tarih: "bicim once taninir" } }, { n: 9, k: "temizleme", ad: "aykiri degerler", s: 0, p: { yontem: "ceyrekler acikligi", carpan: "ortam", karar: "ayri defter" } }, { n: 10, k: "temizleme", ad: "kategorik duzeltme", s: 216, p: { anahtar: "sadelestirilmis", eslesme: "tarife cetveli" } }, { n: 11, k: "temizleme", ad: "metin normallestirme", s: 36, p: { basamak: "dort basamak", kucultme: "dile duyarli" } }, { n: 12, k: "donusturme", ad: "birlestirme", s: 69, p: { tur: "ic", anahtar: "abone_no + donem" } }, { n: 13, k: "donusturme", ad: "yeniden sekillendirme", s: 103, p: { bicim: "genis", bos: "atlanir" } }, { n: 14, k: "donusturme", ad: "gruplama", s: 0, p: { kirilim: "bolge", ozet: "ortalama + yayilim" } }, { n: 15, k: "donusturme", ad: "turetilmis degiskenler", s: 328, p: { turetme: "kisi basi + degisim", tanimsiz: "sebebiyle sayilir" } }, { n: 16, k: "donusturme", ad: "kategorik kodlama", s: 0, p: { bolge: "sirasiz kodlama", memnuniyet: "sirali", siralama: "ortam" } }, { n: 17, k: "donusturme", ad: "hazirlama defteri", s: 0, p: { defter: "her adim", olcu: "giren + cikan + sessiz" } }, ]; export const KARAR = HAT.reduce((a, x) => a + Object.keys(x.p).length, 0); export const ORTAM = HAT.flatMap((x) => Object.entries(x.p) .filter(([, v]) => v === "ortam").map(([k]) => `${x.n}.${k}`)); 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(`hat defteri: ${HAT.length} adim, ${KARAR} karar, ${ORTAM.length} karar ` + `kosum ortamindan geliyor (${ORTAM.join(", ")})`); const y = gen([14, 9, 15, 16]); console.log("\n" + y(["konu", "adim", "karar sayisi", "sessiz kayip"])); for (const k of [...new Set(HAT.map((x) => x.k))]) { const l = HAT.filter((x) => x.k === k); console.log(y([k, l.length, l.reduce((a, x) => a + Object.keys(x.p).length, 0), l.reduce((a, x) => a + x.s, 0)])); } const S = HAT.reduce((a, x) => a + x.s, 0); console.log(y(["toplam", HAT.length, KARAR, S])); console.log(`\nsessiz kaybin dokumu (adim: kayit)`); console.log(" " + HAT.filter((x) => x.s > 0).map((x) => `${x.n}:${x.s}`).join(" ")); const gercek = HAT[11].s; console.log(`toplam ${S} kayit, en buyuk kalem adim 4 (${HAT[3].s}); bunun ${gercek} kaydi ` + `benimsenen hatta gercekten dustu, kalan ${S - gercek} kayit secilmeyen yaygin kararin ` + `olculmus bedelidir`); }
hat defteri: 17 adim, 39 karar, 3 karar kosum ortamindan geliyor (5.tohum, 9.carpan, 16.siralama) konu adim karar sayisi sessiz kayip toplama 5 13 3297 temizleme 6 13 817 donusturme 6 13 500 toplam 17 39 4614 sessiz kaybin dokumu (adim: kayit) 1:142 2:766 3:512 4:1877 6:100 8:465 10:216 11:36 12:69 13:103 15:328 toplam 4614 kayit, en buyuk kalem adim 4 (1877); bunun 69 kaydi benimsenen hatta gercekten dustu, kalan 4545 kayit secilmeyen yaygin kararin olculmus bedelidir
Hattın kendisi burada bir tablo. On yedi adımın her biri bir ad, bir sessiz kayıp kalemi ve bir karar kümesi taşıyor; kararlar toplam 39 ediyor ve üç konuya 13’er dağılıyor. Biçimin tek amacı var: adımı çalıştıran kod ile adımın kararı ayrı ayrı okunabilsin.
Döküm satırı kursun toplamını veriyor. On yedi adımın ölçtüğü sessiz kayıp 4.614 kayıttır; en büyük kalem dördüncü adımdır, çünkü sayfaya bir sütun eklenince hiçbir seçici kırılmaz ve 1.877 kaydın hepsi yanlış alandan okunur. Sayının önemli bir ayrımı var: 4.614’ün yalnız 69’u benimsenen hatta gerçekten düştü — iç birleştirmenin hiç göstermediği aboneler. Kalan 4.545 kayıt, o adımda yaygın olan kararın ölçülmüş bedelidir ve o karar seçilmediği için gerçekleşmedi. Biri hattın gerçek kaybı, öteki kaybın yazılmış olması sayesinde alınmayan riskin büyüklüğüdür.
Aynı Betik, İki Koşum
// kosum.mjs — hattin ortamdan beslenen uc adimi iki kez kosturulur. Ayni veri, // ayni kod, iki kosum. Sonra ayni uc adim betige yazilmis degerlerle kosturulur. import { HAT, KARAR, ORTAM, gen } from "./hat.mjs"; const uretec = (t) => { let s = (Math.imul(t ^ 0x9e3779b9, 2246822507) >>> 0); return () => (s = (s * 1664525 + 1013904223) >>> 0) / 4294967296; }; // Kucuk bir model kume; kurgudur ve yalnizca uc adimi kosturmak icin var. // Her 97. okumada ondalik noktasi kaymis, her 41. okumada yuksek bir deger var. const r0 = uretec(20260218), KUME = []; for (let i = 0; i < 600; i++) { const t = Math.round((6 + r0() * 46) * 100) / 100; KUME.push({ okuma: i % 97 === 0 ? t * 10 : i % 41 === 0 ? t * 2.2 : t, bolge: ["kuzey", "guney", "dogu"][Math.floor(r0() * 3)] }); } const ort = (a) => a.reduce((x, y) => x + y, 0) / a.length; const ADIM = [ ["5 ornekleme", (l, o) => { const r = uretec(o.tohum); return l.map((x) => ({ x, u: r() })).sort((a, b) => a.u - b.u) .slice(0, 200).map((a) => a.x); }], ["9 aykiri ayirma", (l, o) => { const v = l.map((x) => x.okuma).sort((a, b) => a - b); const q = (t) => v[Math.floor(t * (v.length - 1))], a1 = q(0.25), a3 = q(0.75); const ac = a3 - a1; return l.filter((x) => x.okuma >= a1 - o.carpan * ac && x.okuma <= a3 + o.carpan * ac); }], ["16 kodlama esigi", (l, o) => { const a = [...new Set(l.map((x) => x.bolge))]; const d = o.siralama === "alfabetik" ? [...a].sort() : a; const k = Object.fromEntries(d.map((x, j) => [x, j + 1])); return l.filter((x) => k[x.bolge] >= 2); }], ]; const kostur = (o) => ADIM.map(([ad, f]) => { const c = f(KUME, o); return { ad, satir: c.length, ort: ort(c.map((x) => x.okuma)) }; }); // Ortam iki kosumda farkli: tohum saatten, carpan bir yapilandirmadan, siralama // kategori adlarinin geldigi kaynaktan geliyor. Ucu de betikte yazili degil. const R1 = kostur({ tohum: 4711, carpan: 1.5, siralama: "alfabetik" }); const R2 = kostur({ tohum: 8123, carpan: 3.0, siralama: "ilk gorulme" }); const ESIK = 0.0005; // m3; iki ortalama bu esikten yakinsa ayni sayilir const ayni = (a, b) => a.satir === b.satir && Math.abs(a.ort - b.ort) < ESIK; const y = gen([19, 10, 13, 10, 13, 9]); console.log(`ayni veri (${KUME.length} satir), ayni kod, iki kosum:`); console.log("\n" + y(["adim", "R1 satir", "R1 ortalama", "R2 satir", "R2 ortalama", "ayni mi"])); R1.forEach((a, j) => console.log(y([a.ad, a.satir, a.ort.toFixed(3), R2[j].satir, R2[j].ort.toFixed(3), ayni(a, R2[j]) ? "evet" : "hayir"]))); // Duzeltme: uc deger de betige yazilir, ortam artik okunmuyor. const SABIT = { tohum: 4711, carpan: 1.5, siralama: "alfabetik" }; const D1 = kostur(SABIT), D2 = kostur(SABIT); const tutan = D1.filter((a, j) => ayni(a, D2[j])).length; const onceki = R1.filter((a, j) => ayni(a, R2[j])).length; console.log(`\nortamdan beslenen ${ADIM.length} adimin ${onceki} tanesi iki kosumda ayni; ` + `degerler betige yazilinca ${tutan} tanesi ayni. Hattin ${HAT.length} adiminin ` + `${HAT.length - ADIM.length + onceki} tanesi duzeltmeden once, ${HAT.length} tanesi ` + `duzeltmeden sonra yeniden uretilebiliyor`); // Geri okunabilirlik: kararin degeri kosumdan sonra bir yerden okunabiliyor mu. const pay = (a, b) => `${a}/${b} (yuzde ${(100 * a / b).toFixed(0)})`; console.log(`\ngeri okunabilen karar — yalniz hucrelerde ${pay(7, 32)}, betikte defter ` + `tutulmadan ${pay(KARAR - ORTAM.length, KARAR)}, kosum defteriyle ${pay(KARAR, KARAR)}`); console.log(`okunamayan uc karar ortamdan gelenlerdir; defter tutulmazsa kosumdan sonra ` + `hicbir yerden okunamaz`);
ayni veri (600 satir), ayni kod, iki kosum: adim R1 satir R1 ortalama R2 satir R2 ortalama ayni mi 5 ornekleme 200 31.886 200 32.361 hayir 9 aykiri ayirma 590 29.468 593 29.806 hayir 16 kodlama esigi 404 31.965 391 32.968 hayir ortamdan beslenen 3 adimin 0 tanesi iki kosumda ayni; degerler betige yazilinca 3 tanesi ayni. Hattin 17 adiminin 14 tanesi duzeltmeden once, 17 tanesi duzeltmeden sonra yeniden uretilebiliyor geri okunabilen karar — yalniz hucrelerde 7/32 (yuzde 22), betikte defter tutulmadan 36/39 (yuzde 92), kosum defteriyle 39/39 (yuzde 100) okunamayan uc karar ortamdan gelenlerdir; defter tutulmazsa kosumdan sonra hicbir yerden okunamaz
Üst tablo betiğin tek başına neden yetmediğini gösteriyor. Üç adımın parametresi betikte yazılı değil: örneklemenin tohumu saatten, aykırı ayırmanın çarpanı bir yapılandırmadan, kodlamanın sıralaması kategori adlarının geldiği kaynaktan geliyor. Kod iki koşumda aynı, veri de aynı 600 satır; sonuç üçünde de farklı.
Farkların biçimi ayrı. Örnekleme iki koşumda da 200 satır çeker ve ortalamayı 31,886 ile 32,361 m³ arasında oynatır: satır sayısı hiç değişmez, bu yüzden satır sayısına bakan bir denetim hiçbir şey görmez. Aykırı ayırma 590 ile 593 satır bırakır. Kodlama eşiği 404 ile 391 satır seçer — bu, bir önceki dersin bulgusunun hattaki karşılığıdır ve sıralama kararı ortamdan geldiği için artık seçildiği bile görünmez.
Hattın on yedi adımının 14’ü düzeltmeden önce, 17’si üç değer betiğe yazılınca yeniden üretilebiliyor. Düzeltme bir yeniden yazma değil, üç sayının koddan okunur hale getirilmesidir.
Son satır kursun açılışındaki soruyu kapatıyor. Kararlar hücrelerin içindeyken 32 karardan 7’si geri okunabiliyordu, yüzde 22. Betiğe yazıldığında 39 kararın 36’sı okunabilir olur, yüzde 92. Koşum defteri tutulduğunda, yani her adım kendi kararlarını ve satır hesabını çıktıya yazdığında oran 39’da 39 olur. Aradaki fark yeniden üretilebilirliğin durduğu yerdir: betik ne yapabileceğini gösterir, defter ne yapıldığını gösterir.
Özet
- Bir hazırlama hattı, adımların verisi yazıldığında belgelenir: 17 adım, 39 karar, adım başına bir satır hesabı.
- On yedi adımın ölçtüğü sessiz kayıp 4.614 kayıttır; 69’u benimsenen hatta gerçekleşti, 4.545’i seçilmeyen yaygın kararın ölçülmüş bedelidir.
- Parametresi koşum ortamından gelen üç adım aynı veriyle iki koşumda farklı sonuç verir; örneklemede satır sayısı değişmediği için fark satır denetiminden kaçar.
- Değerler betiğe yazılınca yeniden üretilebilen adım sayısı 14’ten 17’ye çıkar.
- Kararın geri okunabilirliği hücrelerde 32’de 7 (yüzde 22), betikte defter tutulmadan 39’da 36 (yüzde 92), koşum defteriyle 39’da 39’dur.
Kurs Kapanışı
On yedi dersin hesabı tek bir tabloda duruyor ve her sayı kendi dersinden okundu.
| Ders | Giren satır | Çıkan satır | Nereye gitti |
|---|---|---|---|
| Toplama 01 dosya biçimleri | 2.076 fiziksel | 2.037 kayıt | naif bölmede 142 sessiz |
| Toplama 02 veritabanından çekme | 1.877 | 1.877 | yanlış birleştirmede 766 sessiz |
| Toplama 03 arayüzlerden toplama | 1.877 | 1.877 | dar kapsamda 477, sayfalamada 35 |
| Toplama 04 yapısal ayrıştırma | 1.877 | 1.877 | 1.877 kayıt yanlış alandan |
| Toplama 05 örnekleme | 1.877 | 200 | 1.677 karar gereği dışarıda, 0 sessiz |
| Temizleme 01 eksik değerler | 2.086 | 2.068 | 18 elendi, 204 dolduruldu |
| Temizleme 02 yinelenen kayıtlar | 2.068 | 1.880 | 188 birleşti, 23 yanlış bağ |
| Temizleme 03 tip dönüşümleri | 1.880 | 1.880 | 0 elendi, yaygında 465 sessiz |
| Temizleme 04 aykırı değerler | 1.880 | 1.816 | 64 ayrı deftere |
| Temizleme 05 kategorik düzeltme | 1.816 | 1.816 | 15 yazım 5 sınıfta |
| Temizleme 06 metin normalleştirme | 1.816 | 1.816 | 1.491 eşleşme kurtarıldı |
| Dönüştürme 01 birleştirme | 3.471 okuma | 3.199 | 169 eşleşmeyen, 103 çift geçen, 69 abone sessiz |
| Dönüştürme 02 yeniden şekillendirme | 3.199 | 1.260 geniş | 581 boş hücre, 103 üzerine yazıldı |
| Dönüştürme 03 gruplama | 3.199 | 5 özet | 3.194 eridi, 7 göz görünmedi |
| Dönüştürme 04 türetilmiş değişkenler | 3.199 | 3.199 | 328 tanımsız, süzgeçte düşer |
| Dönüştürme 05 kategorik kodlama | 3.199 | 3.199 | eşik 2.166 / 1.678 / 1.633 |
| Dönüştürme 06 hazırlama defteri | 3.199 | 3.199 | 39 karar deftere yazıldı |
Bir konunun çıkan satırı sonraki konunun giren satırına eşit değil, çünkü üç konu aynı kurgu ağın üç ayrı çekimiyle çalışır: toplama 1.877 okumayı, temizleme 2.086 satırlık ham çekimi, dönüştürme üç dönemlik 3.471 okumayı ölçer. Uçtan uca taşınan tek bir sayı değil, hesabın kendisidir.
Kursun kuralı bu tablonun okunma biçimidir: hazırlama adımlarının toplamı bir hesaptır; giren ile çıkan arasındaki fark kalem kalem yazılamıyorsa veri hazırlanmamış, yalnız değiştirilmiştir. Kaybını yazamadığın temizlik bir temizlik değildir. On yedi dersin ölçtüğü sessiz kayıp toplamı 4.614 kayıttır ve bu sayının varlığı bir kusur değil kursun çıktısıdır: yazılmayan bir sessiz kayıp sıfır görünür.
On yedi derste küme hazırlandı ve her adımın hesabı yazıldı. Ama bütün bu adımlar tek tek, elle yazılmış küçük kodlarla yapıldı; aynı işi binlerce satırda, tekrarlanabilir ve okunabilir biçimde yapan bir araç takımı hiç kullanılmadı. Sonraki kurs, Python ile Veri Analizi, elle yazılan her adımın bir veri çerçevesi arayüzündeki karşılığını ele alır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.