İçeriğe geç
academia.sh

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. Katman bir tür ve birkaç ayardır, Grafik bir 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.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat