---
title: 'İstatistiksel Programlama Dilleri'
source: 'https://academia.sh/tr/kurslar/python-ile-analiz/istatistiksel-programlama-dilleri'
course: 'Python ile Veri Analizi'
language: tr
updated: '2026-08-17T18:08:43+00:00'
license: 'CC BY-SA 4.0'
---

# İstatistiksel Programlama Dilleri

Aynı analiz — 3.199 satırlık kurgu kümede bölge başına ortalama tüketim ve azalan sırada ilk üç bölge — üç ifade biçiminde yazılır ve üçü de aynı sayıyı verir: yordamsal ifade 6 deyim, 6 ara değişken ve 2 döngü; bütün-nesne ifadesi 4 deyim, 3 ara değişken ve 0 döngü; bildirimsel ifade 1 deyim, 0 ara değişken ve 0 döngü tutar. Yazılan döngü 2'den 0'a inerken koşan döngü 2'den 3'e çıkar: döngü kaybolmaz, yardımcıya taşınır ve bir tane de eklenir. Tek deyimlik ifade 4 kararı yazar, 5 kararı varsayılana bırakır; beş varsayılan tek tek çevrildiğinde doğu ortalaması 24,674 m³ yerine 25,593, 24,814, 24,120 ve 25,540 m³ olur ve sıralama yönü değişince rapor edilen üç bölge tamamen değişir.

Bir önceki konu ölçek sorununu araç değiştirerek çözdü: sütun okundu, parça parça işlendi, hesap
veriye götürüldü. Her adımda değişen şey aracın yerleşimiydi. Değişmeyen tek şey **dilin kendisi**
oldu; analiz baştan sona aynı biçimde, aynı deyimlerle yazıldı ve bu biçimin bir seçim olduğu hiç
sorulmadı.

Bu konu o soruyu sorar. Aynı analiz başka ortamlarda başka biçimlerde ifade edilir ve aradaki fark
hız değil, **ifadenin uzunluğudur**. Bu dersin ilk sayısı budur: aynı analiz kaç deyimde, kaç ara
değişkenle ve kaç döngüyle yazılıyor. Yanında kursun ikinci sayısı durur: ifade kısaldıkça kaç karar
koddan çıkıp varsayılana geçiyor.

- **AO1.** Küme K03'ten devralınır ve **kurgudur**: 3.199 satırlık uzun biçimli okuma tablosu,
  1.329 abone, 10/25/40 m³ tarife basamakları. Tohum koda yazılıdır, sayılar koşumdan koşuma aynıdır.
- **AO2.** Bu derste **hiçbir dil, kütüphane ya da ortam adı geçmez**. Alternatif ortamlar
  **yaklaşımlarıyla** anılır ve yaklaşım Python'da **modellenir**. Modelin amacı bir aracı taklit
  etmek değil, ifade biçimini ölçülebilir kılmaktır.
- **AO3.** Üç yaklaşım şunlardır. **Yordamsal ifade**de iş birimi satırdır: veri tek tek dolaşılır.
  **Bütün-nesne ifadesi (whole-object expression)** analiz odaklı dillerin yaklaşımıdır ve iş birimi
  sütunun tamamıdır: hiçbir döngü yazılmaz, işlem tüm sütuna uygulanır. **Bildirimsel ifade**de
  sonucun tanımı yazılır, yürütme sırası yazılmaz.
- **AO4.** Ölçü **karşılaştırmalı üstünlük değildir**. Kısa ifade iyi, uzun ifade kötü diye bir
  sıralama kurulmaz. Sayılan tek şey deyim, ara değişken, döngü ve varsayılan sayısıdır.

## Aynı Analiz, Üç İfade

Analiz tek bir cümlede tanımlanır: bölge başına ortalama tüketim, azalan sırada ilk üç bölge. Küme
üç ifadenin de girdisidir ve tohum sabittir.

```python
# ortam.py — MODELDIR. K03'un 3.199 satirlik kurgu kumesi ayni tohumla yeniden
# uretilir; hicbir arac, kutuphane ya da ortam taklit edilmez.
import ast
import inspect
import math

TOHUM = 20260218
HAM = 1400
DONEM = ["2026-01", "2026-02", "2026-03"]
TARIFE = [10, 25, 40]
M32 = 0xFFFFFFFF


def karistir(x: int) -> int:
    x = ((x ^ (x >> 16)) * 2246822507) & M32
    x = ((x ^ (x >> 13)) * 3266489909) & M32
    return (x ^ (x >> 16)) & M32


def uretec(t: int):
    s = [karistir(t)]

    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


BOLGE = [("kuzey", 0.28, 21), ("guney", 0.22, 17), ("dogu", 0.18, 26),
         ("bati", 0.14, 14), ("merkez", 0.18, 23)]
_abone, _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 _abone).append(kayit)
_gecerli = {a["abone_no"] for a in _abone}
OKUMA = []
for k in _abone + _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()

print(f"kurgu kume (tohum {TOHUM}): {len(OKUMA)} satir, {len(_gecerli)} abone, "
      f"{sum(o['tuketim_m3'] for o in OKUMA):.1f} m3")
print(f"okunmamis satir (sifir yazilmis): {sum(1 for o in OKUMA if o['tuketim_m3'] == 0)}")
```

```
kurgu kume (tohum 20260218): 3199 satir, 1329 abone, 63060.6 m3
okunmamis satir (sifir yazilmis): 119
```

Üç ifade aynı kümeyi alır. Ölçüm elle değil, kodun kendi ağacından yapılır: her ifadenin kaynağı
ayrıştırılır, gövdesindeki deyimler, atanan adlar ve döngü düğümleri sayılır. Böylece "kaç adım"
sorusunun cevabı bir yorum değil, sayılabilir bir büyüklük olur.

```python
# Bütün-nesne yaklasiminin yardimcilari: islem sutunun tamamina uygulanir.
def sutun(satirlar, ad):
    return [s[ad] for s in satirlar]


def grup_ortalamasi(anahtar, olcu):
    toplam, adet = {}, {}
    for a, v in zip(anahtar, olcu):
        toplam[a] = toplam.get(a, 0.0) + v
        adet[a] = adet.get(a, 0) + 1
    return {a: toplam[a] / adet[a] for a in toplam}


def azalan(esleme):
    return sorted(esleme.items(), key=lambda p: -p[1])


def ilk_n(ciftler, n):
    return ciftler[:n]


# Bildirimsel yaklasimin cozucusu: istek bir tanimdir, yurutme sirasi burada.
def coz(istek):
    a = sutun(istek["kaynak"], istek["grup"])
    o = sutun(istek["kaynak"], istek["olcu"])
    return ilk_n(azalan(grup_ortalamasi(a, o)), istek["ilk"])


YARDIMCI = {"sutun": sutun, "grup_ortalamasi": grup_ortalamasi, "azalan": azalan,
            "ilk_n": ilk_n, "coz": coz}


def yordamsal(satirlar):
    toplam, adet = {}, {}
    for s in satirlar:
        b = s["bolge"]
        toplam[b] = toplam.get(b, 0.0) + s["tuketim_m3"]
        adet[b] = adet.get(b, 0) + 1
    ortalama = {}
    for b in toplam:
        ortalama[b] = toplam[b] / adet[b]
    sirali = sorted(ortalama.items(), key=lambda p: -p[1])
    return sirali[:3]


def butun_nesne(satirlar):
    bolge = sutun(satirlar, "bolge")
    tuketim = sutun(satirlar, "tuketim_m3")
    ortalama = grup_ortalamasi(bolge, tuketim)
    return ilk_n(azalan(ortalama), 3)


def bildirimsel(satirlar):
    return coz({"kaynak": satirlar, "grup": "bolge", "olcu": "tuketim_m3", "ilk": 3})


# Olcum kodun agacindan okunur: deyim sayisi, atanan ad sayisi, dongu dugumleri.
DONGU = (ast.For, ast.While, ast.comprehension)


def agac(f):
    return ast.parse(inspect.getsource(f)).body[0]


def deyim(f):
    return len(agac(f).body)


def ad_sayisi(f):
    g = agac(f)
    return len({n.id for n in ast.walk(g)
                if isinstance(n, ast.Name) and isinstance(n.ctx, ast.Store)})


def yazilan_dongu(f):
    return sum(1 for n in ast.walk(agac(f)) if isinstance(n, DONGU))


# Kosan dongu: ifadenin kendi dongulerine cagirdigi yardimcilarinkiler eklenir.
def kosan_dongu(f, gorulen=None):
    gorulen = set() if gorulen is None else gorulen
    sayi = yazilan_dongu(f)
    for n in ast.walk(agac(f)):
        if isinstance(n, ast.Call) and isinstance(n.func, ast.Name):
            ad = n.func.id
            if ad in YARDIMCI and ad not in gorulen:
                gorulen.add(ad)
                sayi += kosan_dongu(YARDIMCI[ad], gorulen)
    return sayi


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))


IFADE = [("yordamsal", yordamsal), ("butun-nesne", butun_nesne),
         ("bildirimsel", bildirimsel)]
y = hiza([16, 8, 15, 16, 14])
print("\n" + y(["ifade", "deyim", "ara degisken", "yazilan dongu", "kosan dongu"]))
for ad, f in IFADE:
    print(y([ad, deyim(f), ad_sayisi(f), yazilan_dongu(f), kosan_dongu(f)]))

sonuc = [f(OKUMA) for _, f in IFADE]
ayni = all(s == sonuc[0] for s in sonuc)
print(f"\nucu de ayni sonucu veriyor: {'evet' if ayni else 'hayir'}")
print("  " + ", ".join(f"{b} {v:.3f}" for b, v in sonuc[0]))
```

```
ifade              deyim   ara degisken   yazilan dongu   kosan dongu
yordamsal              6              6               2             2
butun-nesne            4              3               0             3
bildirimsel            1              0               0             3

ucu de ayni sonucu veriyor: evet
  dogu 24.674, merkez 22.396, kuzey 20.210
```

Alt satır dersin çıpasıdır: üç ifade de aynı üç bölgeyi ve aynı üç sayıyı verir. Fark sonuçta değil,
**yazımdadır**. Yordamsal ifade 6 deyim tutar ve 6 ad bağlar; bunların dördü ara sonuçtur ve hiçbiri
rapora girmez. Bütün-nesne ifadesi 4 deyime ve 3 ada iner, çünkü artık satır dolaşılmaz: `bolge` ve
`tuketim` iki sütun olarak alınır ve ortalama sütunun tamamına uygulanır. Bildirimsel ifade tek
deyimdir ve hiçbir ad bağlamaz; yazılan şey sonucun tarifidir.

İkinci satırdaki asıl değişiklik sayıda değil, **iş biriminde** gerçekleşiyor. Yordamsal ifadede
kodun konuştuğu şey `s` adlı tek bir satırdır ve toplam ile adet o satırın alanlarından büyür;
analizin nesnesi bir kayıttır. Bütün-nesne ifadesinde kodun konuştuğu şey `bolge` ve `tuketim` adlı
iki sütundur; tek bir satırın adı bile geçmez. İstatistiksel programlama dillerinin yaklaşımı
buradan gelir: veri kaydın değil, **alanın** birimiyle ele alınır ve işlem alanın tamamına
uygulandığı için dolaşma kodun görünen kısmından tümüyle çıkar.

## Döngü Kaybolmadı, Taşındı

Tablonun son iki sütunu birbirinin tersine gidiyor. **Yazılan döngü** 2'den 0'a iner, **koşan
döngü** 2'den 3'e çıkar. Bu, soyutlamanın en sık yanlış okunan yerlerinden biridir: döngüyü yazmayı
bırakmak döngüyü ortadan kaldırmaz, yalnız yerini değiştirir.

Yordamsal ifade kümeyi iki kez dolaşır: bir kez toplam ve adet için, bir kez bölme için. Bütün-nesne
ifadesi hiç döngü yazmaz, ama çağırdığı yardımcılar üç döngü koşturur — `sutun` her çağrıldığında
kümeyi bir kez tarar ve iki kez çağrılır, `grup_ortalamasi` bir tarama ve bir birleştirme yapar.
İfade kısaldıkça geçiş sayısı **azalmaz**, bu örnekte artar. Kısalık ile geçiş sayısı arasında bir
bağ olduğunu varsaymak, ölçülmemiş bir iddiadır.

Bunun karşılığında elde edilen şey de sayılabilir: yordamsal ifadedeki dört ara ad — `toplam`,
`adet`, `ortalama`, `sirali` — bütün-nesne ifadesinde üçe, bildirimsel ifadede sıfıra iner. Ara ad,
okunması gereken ve yanlış kullanılabilecek bir şeydir; sayısının düşmesi ifadenin okunma yükünü
düşürür. Bedeli, bir sonraki bölümün konusudur.

Ölçünün neyi saymadığı da yazılmalıdır. Tablo yalnız **analizi yazan kişinin yazdığı** deyimleri
sayar; yardımcıların kendi gövdeleri sayıya girmez. Dört yardımcı ile çözücü bir arada on beş
deyimden fazla tutar ve bu deyimler bir yerde birinin yazdığı deyimlerdir. Soyutlamanın kazancı iş
miktarının azalması değil, **aynı deyimlerin bir kez yazılıp çok kez kullanılmasıdır**; iki sütun
farklı üç analizde de aynı `sutun` çağrısıyla alınır. Bu yüzden ölçü bir üstünlük sıralaması vermez,
yalnız yükün nereye taşındığını gösterir.

## Tek Deyimin Beş Kararı

Bildirimsel ifade dört şey yazıyor: kaynak, grup alanı, ölçü alanı ve kaç satır isteneceği. Analizin
sonucunu belirleyen kararların hepsi bunlar değildir. Aşağıdaki çözücü, aynı isteği eksiksiz bir
varsayılan kümesiyle karşılar ve her varsayılan tek tek çevrilir.

```python
# Ayni bildirimsel istek, bu kez butun varsayilanlari adiyla tasiyan bir cozucude.
VARSAYILAN = {"eksik": "say", "agirlik": "satir", "ozet": "ortalama",
              "donem": "hepsi", "yon": "azalan"}


def ortanca(v):
    s = sorted(v)
    n = len(s)
    return s[n // 2] if n % 2 else (s[n // 2 - 1] + s[n // 2]) / 2


def coz_tam(istek):
    a = dict(VARSAYILAN)
    a.update(istek)
    satirlar = [s for s in istek["kaynak"]
                if (a["donem"] == "hepsi" or s["donem"] == a["donem"])
                and (a["eksik"] == "say" or s["tuketim_m3"] > 0)]
    if a["agirlik"] == "abone":
        birim = {}
        for s in satirlar:
            birim.setdefault(s["abone_no"], (s[a["grup"]], []))[1].append(s[a["olcu"]])
        satirlar = [{a["grup"]: g, a["olcu"]: sum(v) / len(v)} for g, v in birim.values()]
    kova = {}
    for s in satirlar:
        kova.setdefault(s[a["grup"]], []).append(s[a["olcu"]])
    ozet = {g: (sum(v) / len(v) if a["ozet"] == "ortalama" else ortanca(v))
            for g, v in kova.items()}
    sirali = sorted(ozet.items(), key=lambda p: p[1], reverse=a["yon"] == "azalan")
    return sirali[:a.get("ilk", len(sirali))]


TEMEL = {"kaynak": OKUMA, "grup": "bolge", "olcu": "tuketim_m3", "ilk": 3}
DEGISIM = [("okunmamis satir", "eksik", "say", "dus"),
           ("olcunun agirligi", "agirlik", "satir", "abone"),
           ("ozet islevi", "ozet", "ortalama", "ortanca"),
           ("donem kapsami", "donem", "hepsi", "2026-01"),
           ("siralama yonu", "yon", "azalan", "artan")]
taban = dict(coz_tam(TEMEL))["dogu"]
y2 = hiza([20, 12, 12, 14, 12, 24])
print("\n" + y2(["gizlenen karar", "varsayilan", "dogu m3", "degistirilen", "dogu m3",
                 "rapor edilen ilk uc"]))
degerler = [taban]
for ad, anahtar, onceki, sonra in DEGISIM:
    istek = {**TEMEL, anahtar: sonra}
    ucu = coz_tam(istek)
    d = dict(coz_tam({k: v for k, v in istek.items() if k != "ilk"}))["dogu"]
    degerler.append(d)
    print(y2([ad, onceki, f"{taban:.3f}", sonra, f"{d:.3f}",
              " ".join(b for b, _ in ucu)]))
print(f"\ntek deyimlik ifade {len(TEMEL)} karari yaziyor, {len(VARSAYILAN)} karari "
      f"varsayilana birakiyor")
print(f"varsayilanlar yazilirsa istek {len(TEMEL)} -> {len(TEMEL) + len(VARSAYILAN)} "
      f"anahtar olur ve ifade hala 1 deyimdir")
print(f"dogu ortalamasi {min(degerler):.3f} ile {max(degerler):.3f} arasinda "
      f"{max(degerler) - min(degerler):.3f} m3 oynuyor")
```

```
gizlenen karar        varsayilan     dogu m3  degistirilen     dogu m3     rapor edilen ilk uc
okunmamis satir              say      24.674           dus      25.593       dogu merkez kuzey
olcunun agirligi           satir      24.674         abone      24.814       dogu merkez kuzey
ozet islevi             ortalama      24.674       ortanca      24.120       dogu merkez kuzey
donem kapsami              hepsi      24.674       2026-01      25.540       dogu merkez kuzey
siralama yonu             azalan      24.674         artan      24.674        bati guney kuzey

tek deyimlik ifade 4 karari yaziyor, 5 karari varsayilana birakiyor
varsayilanlar yazilirsa istek 4 -> 9 anahtar olur ve ifade hala 1 deyimdir
dogu ortalamasi 24.120 ile 25.593 arasinda 1.473 m3 oynuyor
```

Tek deyim dört karar yazıyor, beş kararı varsayılana bırakıyor. Beş varsayılan tek tek çevrildiğinde
doğu ortalaması 24,674 m³ yerine sırasıyla 25,593 — 24,814 — 24,120 — 25,540 m³ olur; en düşük ile
en yüksek arasında **1,473 m³**, yani taban değerin yaklaşık yüzde altısı kadar bir açıklık vardır.
Beşincisi sayıyı hiç oynatmaz ama rapor edilen üç bölgeyi tamamen değiştirir: azalan sırada doğu,
merkez ve kuzey yazılır, artan sırada batı, güney ve kuzey.

Buradaki asıl gözlem şudur: aynı beş karar **yordamsal ifadede de vardır**. Orada da okunmamış
satırlar sayılmıştır, ağırlık satırdır ve özet aritmetik ortalamadır. Fark, kararların
**yazılabileceği yer sayısıdır**. Yordamsal ifadede altı deyimin beşi bir karara karşılık gelir ve
her biri değiştirilebilir bir satırdır. Tek deyimlik ifadede böyle bir satır yoktur; karar ancak
isteğe bir anahtar olarak eklenirse görünür hale gelir. Varsayılanların hepsi açıkça yazıldığında
istek dört anahtardan dokuz anahtara çıkar ve ifade **hâlâ tek deyimdir** — kaydın bedeli deyim
değil, anahtardır.

Kursun kuralı burada tam olarak karşılığını buluyor. Bir soyutlama işi kısalttığı kadar kararı da
gizler; varsayılanını bilmediğin bir işlev, senin adına karar veren bir işlevdir. Kısa ifade bu
yüzden kötü değildir — kararın nerede yazıldığını bilmemek kötüdür.

## Özet

- Aynı analiz üç ifade biçiminde yazıldığında aynı sonucu verir: doğu 24,674 — merkez 22,396 —
  kuzey 20,210 m³.
- İfadenin ölçüsü deyim, ara değişken ve döngü sayısıdır: yordamsal 6/6/2, bütün-nesne 4/3/0,
  bildirimsel 1/0/0.
- Yazılan döngü 2'den 0'a inerken koşan döngü 2'den 3'e çıkar; soyutlama döngüyü yok etmez, taşır
  ve bu örnekte bir tane de ekler.
- Tek deyimlik ifade 4 kararı yazar, 5 kararı varsayılana bırakır; beş varsayılan çevrildiğinde doğu
  ortalaması 1,473 m³ genişliğinde bir aralıkta oynar ve sıralama yönü rapor edilen üç bölgeyi
  tamamen değiştirir.
- Aynı kararlar yordamsal ifadede de vardır; değişen şey kararın yazılabileceği yer sayısıdır.

## Sonraki Adım

Bildirimsel ifade tek deyime indi, ama bu inişin bir bedeli var: dört anahtarlık bir sözlük, bir
analizin ne yaptığını sırasıyla anlatmaz. Sonraki ders aradaki biçimi ölçer — dönüştürmeyi tek tek
**fiillerden** kurulu bir zincir olarak yazan yaklaşım. Ölçü aynı ailedendir: aynı yedi adımlık
dönüştürme ara değişkenlerle yazıldığında kaç ad bağlanıyor, iç içe çağrıyla yazıldığında okuma
sırası yürütme sırasıyla kaç adımda örtüşüyor, zincir olarak yazıldığında hangi ara sonucun satır
sayısı görünmez oluyor.
