Ders 21 / 22
Grafik Dilbilgisi
Aynı sütun grafiği iki yolla kurulur: hazır bir çağrı 9 bağımsız değişken alır, katmanlı kuruluş 5 katman tutar ve ikisi de aynı değerleri verir. Üzerine bir referans çizgisi eklendiğinde hazır çağrının imzası 9'dan 11'e çıkar ve önceki kurulumdan hiçbir kalem yeniden kullanılmaz; katmanlı kuruluş 5'ten 6 katmana çıkar ve 5 katman aynen kalır. Gizlenen karar istatistik katmanındadır: aynı beş katmanın dördü sabit tutulup yalnız istatistik değiştirildiğinde en uzun çubuk kuzey, doğu ve yine kuzey olur — adet 921, ortalama 24,674 m³, toplam 18.613,81 m³ üç ayrı sıralama üretir. Konum ayarı da aynı biçimde davranır: 6 katman değişmeden dururken doğu/2 için okunan sayı 281'den 0,504'e iner.
İçindekiler
Bir önceki ders dönüştürmeyi fiillerden kurdu ve her fiilin bir öncekinin çıktısını aldığını gösterdi. Görselleştirmede de benzer bir kuruluş vardır, ama parçalar birbirini izlemez — üst üste biner. Grafik dilbilgisi (grammar of graphics) bir grafiği tek bir çağrı olarak değil, birbirinden bağımsız katmanların toplamı olarak ele alır: veri, eşleme, istatistik, geometri, ölçek, konum.
Bu dersin sayısı katman sayısıdır: aynı grafik hazır bir çağrıyla kurulduğunda kaç kalem yazılıyor, katmanlarla kurulduğunda kaç katman tutuyor, ve grafik büyüdüğünde kaç kalem yeniden kullanılıyor. Yanında kursun ikinci sayısı durur: bir katman yazılmadığında onun yerine hangi varsayılan geçiyor ve grafiğin okunan sayısı ne oluyor.
- AO9. Küme K03’ten devralınır ve kurgudur: 3.199 satır, 1.329 abone, 10/25/40 m³ tarife basamakları. Tohum koda yazılıdır.
- AO10. Katmanlı grafik standart kitaplıkla modellenir.
Katmanbir tür ve birkaç ayardır,Grafikbir katman listesidir; çizim metin çubuklarıyla yapılır, çünkü ölçülen şey biçim değil katman sayısıdır. Hiçbir araç ya da kitaplık taklit edilmez. - AO11. Grafik türünün eksen alanının ölçeğine uyup uymadığı bu derste ölçülmez; o soru Elektronik Tablolarla Analiz kursunun Temel Grafikler dersinde ölçüldü. Burada tür yalnız bir geometri katmanıdır ve sayılan şey katmanların sayısı ile birbirinden bağımsız olup olmadığıdır.
- AO12. İki sayı yan yana durur. Kazanç grafiği genişletirken yeniden kullanılan kalem sayısıdır. Gizlenen karar yazılmayan katmandır: istatistik ve konum katmanı yazılmadığında grafik yine çizilir, ama çubukların boyu başka bir şeyi gösterir.
Bir Grafik Kaç Katman
# grafik.py — MODELDIR. Once K03'un 3.199 satirlik kurgu kumesi ayni tohumla # uretilir, sonra katmanli gorsellestirme standart kitaplikla modellenir. import inspect import math TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF DONEM, TARIFE = ["2026-01", "2026-02", "2026-03"], [10, 25, 40] BOLGE = [("kuzey", 0.28, 21), ("guney", 0.22, 17), ("dogu", 0.18, 26), ("bati", 0.14, 14), ("merkez", 0.18, 23)] def uretec(t: int): x = ((t ^ (t >> 16)) * 2246822507) & M32 x = ((x ^ (x >> 13)) * 3266489909) & M32 s = [(x ^ (x >> 16)) & M32] def sonraki() -> float: s[0] = (s[0] * 1664525 + 1013904223) & M32 return s[0] / 4294967296 return sonraki def ayrik(u: float, w: list[float]) -> int: t = 0.0 for i, x in enumerate(w): t += x if u < t: return i return len(w) - 1 _kalan, _elenen = [], [] for i in range(HAM): r = uretec(TOHUM + i) b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])] kayit = {"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} (_elenen if r() < 0.046 else _kalan).append(kayit) _gecerli = {k["abone_no"] for k in _kalan} OKUMA = [] for k in _kalan + _elenen: r = uretec(TOHUM + 7000 + k["abone_no"]) for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])): t = 0.0 if r() < 0.038 else math.floor( k["taban"] * math.exp((r() + r() + r() - 1.5) * 0.62) * (1 - d * 0.05) * 100 + 0.5) / 100 if k["abone_no"] not in _gecerli: r() continue OKUMA.append({"abone_no": k["abone_no"], "bolge": k["bolge"], "donem": DONEM[d], "tuketim_m3": t, "memnuniyet": k["memnuniyet"], "basamak": 1 if t < TARIFE[0] else 2 if t < TARIFE[1] else 3 if t < TARIFE[2] else 4}) r() class Katman: """Katmanli gorsellestirmenin MODELI: katman bir tur ve birkac ayardir.""" def __init__(self, tur, **ayar): self.tur, self.ayar = tur, ayar def imza(self): return (self.tur, tuple(sorted( (k, f"{len(v)} satir" if isinstance(v, list) else str(v)) for k, v in self.ayar.items()))) OZET = {"adet": lambda v, a: float(len(v)), "ortalama": lambda v, a: sum(s[a] for s in v) / len(v), "toplam": lambda v, a: sum(s[a] for s in v)} class Grafik: def __init__(self, katmanlar=()): self.katmanlar = list(katmanlar) def ekle(self, *k): return Grafik(self.katmanlar + list(k)) def degistir(self, k): return Grafik([k if e.tur == k.tur else e for e in self.katmanlar]) def ayar(self, tur, **yoksa): for k in self.katmanlar: if k.tur == tur: return {**yoksa, **k.ayar} return yoksa # Katmanlar sirayla islenir: veri kovalanir, istatistik uygulanir, konum ayarlanir. def deger(self): veri = self.ayar("veri", satirlar=[])["satirlar"] e = self.ayar("eslesme") ozet = self.ayar("istatistik", ozet="adet")["ozet"] kova = {} for s in veri: kova.setdefault((s[e["x"]], s[e["renk"]] if "renk" in e else None), []).append(s) d = {a: OZET[ozet](v, e["y"]) for a, v in kova.items()} if self.ayar("konum", ayar="yigilmis")["ayar"] == "oranli": butun = {} for (x, _), v in d.items(): butun[x] = butun.get(x, 0.0) + v d = {a: v / butun[a[0]] for a, v in d.items()} return d def ciz(self, baslik): d = self.deger() alt = self.ayar("olcek", alt=0.0)["alt"] ust = max(d.values()) print(f"{baslik} — {len(self.katmanlar)} katman") for (x, r), v in sorted(d.items(), key=lambda p: -p[1]): n = round(24 * (v - alt) / (ust - alt)) if ust > alt else 0 print(f" {x if r is None else f'{x}/{r}':<14}{v:9.3f} " + "#" * max(0, n)) for k in self.katmanlar: if k.tur == "geometri" and k.ayar.get("bicim") == "cizgi": v = k.ayar["deger"] print(f" {k.ayar['etiket']:<14}{v:9.3f} " + "-" * max(0, round(24 * (v - alt) / (ust - alt)))) TEMEL = Grafik().ekle( Katman("veri", satirlar=OKUMA), Katman("eslesme", x="bolge", y="tuketim_m3"), Katman("istatistik", ozet="ortalama"), Katman("geometri", bicim="cubuk"), Katman("olcek", eksen="y", alt=0.0)) TEMEL.ciz("bolge basina ortalama tuketim (m3)")
bolge basina ortalama tuketim (m3) — 5 katman dogu 24.674 ######################## merkez 22.396 ###################### kuzey 20.210 #################### guney 16.602 ################ bati 13.778 #############
Grafik beş katmandan kuruldu ve her katman tek bir soruya cevap veriyor. Veri katmanı hangi satırların çizileceğini söyler. Eşleme hangi alanın hangi eksene gideceğini söyler. İstatistik katmanı ham satırlardan çizilecek sayının nasıl türetileceğini söyler — burada her bölgenin ortalaması. Geometri katmanı o sayının hangi biçimde çizileceğini, ölçek katmanı ekseni söyler.
Bu ayrımın önemi katmanların birbirinden bağımsız olmasıdır. Geometriyi çubuktan noktaya çevirmek öbür dört katmana dokunmaz; istatistiği ortalamadan adete çevirmek geometriyi değiştirmez. Bir grafik, seçeneklerin sabit bir listesi değil, birleştirilebilir parçalardan kurulmuş bir cümledir.
Bağımsızlık, katmanların sırasız olduğu anlamına gelmez. deger yöntemi işi belli bir sırayla
yapar: önce veri eşlemeye göre kovalara ayrılır, sonra her kovaya istatistik uygulanır, en sonda
konum ayarı uygulanır. Katmanlar sayfaya hangi sırayla yazılırsa yazılsın bu işlem sırası değişmez;
değişen tek şey hangi katmanın listede bulunduğudur. Fiil zincirinde sıra yazımın kendisiydi, burada
sıra dilbilgisinin kuralıdır ve yazımdan okunmaz.
Katman Eklemek, Çağrıyı Genişletmek
Aynı grafik hazır bir çağrıyla da kurulabilir: bütün kararlar tek bir imzada toplanır ve çağıran kişi yalnız bağımsız değişkenleri doldurur. İkisinin farkı grafik büyüdüğünde ortaya çıkar.
def hazir_cubuk(satirlar, x, y, ozet, renk=None, konum="yigilmis", alt=0.0, ust=None, baslik=""): """Hazir cagri MODELI: butun kararlar tek bir imzada toplanir.""" return Grafik().ekle(Katman("veri", satirlar=satirlar), Katman("eslesme", x=x, y=y), Katman("istatistik", ozet=ozet), Katman("geometri", bicim="cubuk"), Katman("olcek", eksen="y", alt=alt)) # Referans cizgisi eklemek icin imzaya iki bagimsiz degisken daha girmesi gerekir. def hazir_cubuk_referansli(satirlar, x, y, ozet, renk=None, konum="yigilmis", alt=0.0, ust=None, baslik="", referans=None, referans_etiket=""): g = hazir_cubuk(satirlar, x, y, ozet, renk, konum, alt, ust, baslik) return g if referans is None else g.ekle( Katman("geometri", bicim="cizgi", etiket=referans_etiket, deger=referans)) GENEL = sum(s["tuketim_m3"] for s in OKUMA) / len(OKUMA) REFERANSLI = TEMEL.ekle(Katman("geometri", bicim="cizgi", etiket="genel ortalama", deger=round(GENEL, 3))) eski = [k.imza() for k in TEMEL.katmanlar] kalan = sum(1 for k in REFERANSLI.katmanlar if k.imza() in eski) def arg(f): return len(inspect.signature(f).parameters) def hiza(w): return lambda h: "".join(str(v).ljust(w[0]) if j == 0 else str(v).rjust(w[j]) for j, v in enumerate(h)) ayni_mi = hazir_cubuk(OKUMA, "bolge", "tuketim_m3", "ortalama").deger() == TEMEL.deger() print(f"hazir cagri ile katmanli kurulus ayni degerleri veriyor: " f"{'evet' if ayni_mi else 'hayir'}") y = hiza([22, 16, 22, 22]) print("\n" + y(["kurulus", "temel grafik", "referans eklenince", "yeniden kullanilan"])) print(y(["hazir cagri (argum.)", arg(hazir_cubuk), arg(hazir_cubuk_referansli), 0])) print(y(["katman listesi", len(TEMEL.katmanlar), len(REFERANSLI.katmanlar), kalan])) print() REFERANSLI.ciz("ayni grafik, referans cizgisi eklenmis")
hazir cagri ile katmanli kurulus ayni degerleri veriyor: evet kurulus temel grafik referans eklenince yeniden kullanilan hazir cagri (argum.) 9 11 0 katman listesi 5 6 5 ayni grafik, referans cizgisi eklenmis — 6 katman dogu 24.674 ######################## merkez 22.396 ###################### kuzey 20.210 #################### guney 16.602 ################ bati 13.778 ############# genel ortalama 19.713 -------------------
İlk satır çıpadır: iki kuruluş aynı değerleri verir, yani ölçülen şey sonuç değil yapıdır. Hazır çağrı temel grafiği 9 bağımsız değişkenle kurar, katman listesi 5 katmanla. Sayı olarak hazır çağrı daha az kalem tutuyor gibi görünmez, ama asıl ayrım ikinci sütunda.
Grafiğe genel ortalamayı gösteren bir çizgi eklendiğinde hazır çağrının imzası 9’dan 11’e çıkar. Bu, o çağrıyı kullanan her yerin gördüğü yeni bir imzadır ve önceki kurulumdan yeniden kullanılan kalem sayısı sıfırdır: çağrı bir bütündür, parçası taşınamaz. Katmanlı kuruluşta liste 5’ten 6’ya çıkar ve 5 katman aynen kalır; eklenen tek şey bir geometri katmanıdır. Genişleme burada listeye, orada imzaya yazılır.
Bunun bir de ters yönü var ve yazılmalıdır. Hazır çağrı, sık kullanılan bir grafiği tek satırda verir ve beş katmanı elle dizmeyi gerektirmez; katmanlı kuruluşta aynı grafiği kuran herkes aynı beş katmanı yeniden yazar. Ölçü bir üstünlük sıralaması değildir: hazır çağrı tekrarı, katmanlı kuruluş genişlemeyi ucuzlatır.
İstatistik Katmanı Yazılmazsa
Katmanların bağımsızlığının bedeli, bir katman yazılmadığında grafiğin hata vermeden çizilmesidir. Model yazılmayan katmanın yerine bir varsayılan koyar ve çubuklar yine görünür.
y2 = hiza([14, 12, 12, 12, 12, 12, 16]) BOLGELER = ("kuzey", "dogu", "merkez", "guney", "bati") print(y2(["istatistik"] + list(BOLGELER) + ["en uzun cubuk"])) uzun = [] for ozet in ("adet", "ortalama", "toplam"): g = TEMEL.degistir(Katman("istatistik", ozet=ozet)) d = {a[0]: v for a, v in g.deger().items()} uzun.append(max(d.items(), key=lambda p: p[1])[0]) print(y2([ozet] + [f"{d[b]:.3f}" for b in BOLGELER] + [uzun[-1]])) print(f"\nayni {len(TEMEL.katmanlar)} katmanin dordu ayni; yalniz istatistik katmani " f"degisti ve en uzun cubuk {' -> '.join(uzun)} oldu") RENKLI = Grafik([Katman("veri", satirlar=OKUMA), Katman("eslesme", x="bolge", y="tuketim_m3", renk="basamak"), Katman("istatistik", ozet="adet"), Katman("geometri", bicim="cubuk"), Katman("olcek", eksen="y", alt=0.0)]) y3 = hiza([14, 12, 12, 12, 12]) print("\n" + y3(["konum ayari", "dogu/1", "dogu/2", "dogu/3", "dogu/4"])) ikinci = [] for ayar in ("yigilmis", "oranli"): d = RENKLI.ekle(Katman("konum", ayar=ayar)).deger() ikinci.append(d[("dogu", 2)]) print(y3([ayar] + [f"{d[('dogu', b)]:.3f}" for b in (1, 2, 3, 4)])) print(f"\nkatman sayisi {len(RENKLI.katmanlar) + 1} her iki ayarda da ayni; tek bir " f"katmanin tek ayari degisti ve dogu/2 icin okunan sayi {ikinci[0]:.0f} yerine " f"{ikinci[1]:.3f} oldu")
istatistik kuzey dogu merkez guney bati en uzun cubuk adet 921.000 557.000 600.000 645.000 476.000 kuzey ortalama 20.210 24.674 22.396 16.602 13.778 dogu toplam 18613.810 13743.340 13437.310 10708.020 6558.150 kuzey ayni 5 katmanin dordu ayni; yalniz istatistik katmani degisti ve en uzun cubuk kuzey -> dogu -> kuzey oldu konum ayari dogu/1 dogu/2 dogu/3 dogu/4 yigilmis 21.000 281.000 225.000 30.000 oranli 0.038 0.504 0.404 0.054 katman sayisi 6 her iki ayarda da ayni; tek bir katmanin tek ayari degisti ve dogu/2 icin okunan sayi 281 yerine 0.504 oldu
Üç satır aynı veriyi, aynı eşlemeyi, aynı geometriyi ve aynı ölçeği kullanıyor. Değişen tek şey istatistik katmanıdır ve grafiğin söylediği şey üç kez değişiyor. Adet seçildiğinde en uzun çubuk kuzeydedir, çünkü kuzeyde 921 okuma vardır. Ortalama seçildiğinde en uzun çubuk doğuya geçer, çünkü doğu 557 okumayla en az kalabalık ama en yüksek tüketimli bölgedir. Toplam seçildiğinde çubuk kuzeye geri döner. Üçü de doğrudur ve üçü de aynı sütun grafiğidir; hangisinin çizildiğini söyleyen tek şey yazılmış ya da yazılmamış olan istatistik katmanıdır.
Konum ayarı aynı davranışı bir kez daha gösterir. Altı katman iki koşumda da birebir aynıdır; tek fark konum katmanının ayarıdır. Yığılmış ayarda doğu bölgesinin ikinci tarife basamağında 281 okuma vardır ve çubuğun boyu bir sayıdır. Oranlı ayarda aynı yer 0,504 olur ve çubuğun boyu bir paydır. Bir okuyucu ikinci grafiğe bakıp “doğuda ikinci basamak yarıya yakın” der ve haklıdır; ilkine bakıp “doğuda ikinci basamakta 281 okuma var” der ve o da haklıdır. Kaç okuma olduğu ikinci grafikten, payın ne olduğu ilkinden okunamaz.
Kursun kuralı grafikte de aynen geçerlidir: bir soyutlama işi kısalttığı kadar kararı da gizler. Katmanlı kuruluşun sağladığı şey kararların adlandırılmış olmasıdır — istatistik bir katmandır, konum bir katmandır ve grafiğin listesine bakan biri hangisinin yazıldığını görebilir. Yazılmayan katman ise varsayılana düşer ve grafik yine çizilir; sayfaya bakan kişinin elinde çubuğun neyi ölçtüğünü söyleyen bir kayıt kalmaz.
Özet
- Aynı sütun grafiği hazır çağrıyla 9 bağımsız değişkende, katmanlı kuruluşla 5 katmanda kurulur ve ikisi de aynı değerleri verir.
- Referans çizgisi eklendiğinde hazır çağrının imzası 9’dan 11’e çıkar ve yeniden kullanılan kalem sayısı 0’dır; katman listesi 5’ten 6’ya çıkar ve 5 katman aynen kalır.
- Hazır çağrı tekrarı, katmanlı kuruluş genişlemeyi ucuzlatır; ölçü bir üstünlük sıralaması değildir.
- İstatistik katmanı değiştiğinde grafiğin dört katmanı sabit kalır ama en uzun çubuk kuzey, doğu ve yine kuzey olur: adet 921, ortalama 24,674 m³, toplam 18.613,81 m³.
- Konum ayarı katman sayısını değiştirmeden okunan sayıyı değiştirir: doğu bölgesinin ikinci basamağı yığılmış ayarda 281, oranlı ayarda 0,504 olarak okunur.
Sonraki Adım
Üç ders üç yaklaşımı ölçtü: aynı analizin kaç deyimde ifade edildiği, dönüştürmenin kaç fiil ve kaç ara değişkenle yazıldığı, grafiğin kaç katmanla kurulduğu. Hepsinde ölçü ifadenin biçimiydi ve hiçbirinde bir ortamın öbüründen iyi olduğu söylenmedi. Geriye seçimin kendisi kalıyor: bir ekip hangi ortamda çalışacağına neye bakarak karar verir. Sonraki ders bunu ölçüte bağlar — ekibin eldeki becerisi, çevresindeki hazır parçaların kapsamı ve işin üretime taşınabilirliği — ve üç ortamı üç ölçütte sayıyla karşılaştırıp seçimin hangi ölçütte değiştiğini yazar. Kurs orada kapanır ve yirmi iki dersin kazancıyla gizlenen kararını tek bir tabloda sayar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.