İçeriğe geç
academia.sh

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.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat