---
title: 'Kohort ve Huni Analizi'
source: 'https://academia.sh/tr/kurslar/kesifsel-analiz/kohort-ve-huni-analizi'
course: 'İstatistiksel Analiz ve Keşifsel Veri Analizi'
language: tr
updated: '2026-08-17T18:08:47+00:00'
license: 'CC BY-SA 4.0'
---

# Kohort ve Huni Analizi

Kohort tanımının aynı kümeden kaç ayrı elde tutma oranı çıkardığının sayılması: gözlenemeyen kohortu sıfır sayan kural 0,619, dışlayan kural 0,867 verir ve üç dönemlik pencerenin dışında 3.199 okumanın 843'ü kalır. Giriş penceresi dönem alındığında iki gözlenebilir kohort ve 0,009 oran açıklığı, beş hafta alındığında altı kohort ve 0,040 açıklık çıkar; en dar oynama payı 0,087 olduğu için açıklığın tamamı tek bir kohortun payının içine sığar. Huni yalnız toplulaştırma tersine dönmesi kadar geçer: toplulaştırılmış fark -0,237 iken gözlenebilir iki kohortun ikisinde de fark +0,083 ve +0,028'dir.

Önceki ders bir katsayının kırılıma göre yön değiştirdiğini gösterdi, ama kırılım hep bölgeydi ve
zaman hiç işin içine girmedi. Aboneler ağa aynı anda katılmıyor ve aynı süre boyunca izlenmiyor.
Bir aboneyi kayıt açıldıktan bir dönem sonra da okuyabiliyor olmak bir başarıdır ve bu başarının
oranına **elde tutma** denir.

Bu dersin sayısı **kohort tanımının oynattığı elde tutma oranıdır**. Kohort, giriş dönemine göre
kurulan kümedir ve tanımı iki karar içerir: giriş penceresi ne kadar geniştir ve gözlem penceresi
nerede kapanır. İki karar da savunulabilir, ikisi de aynı kümeden başka bir oran çıkarır. Dönüşüm
hunisinin adım hesabı burada tekrarlanmaz; adım dönüşümü, terk oranı ve kümülatif dönüşüm
Kullanıcı Deneyimi kursunun Dönüşüm Hunisi dersinde ölçüldü. Huni bu derse yalnız
**toplulaştırma tersine dönmesi** kadar girer.

- **UI36.** Küme K03'ten devralınır ve **kurgudur**: 3.199 okuma, 1.329 abone, üç dönem, beş bölge.
- **UI37.** Giriş haftası alanı da **kurgudur**: ölçüm ağı bölgelere aynı anda ulaşmamıştır, bu
  yüzden giriş dönemi dağılımı bölgeye bağlıdır.
- **UI38.** Okuma indisi bu derste **girişten sonraki dönemi** verir; takvim dönemi giriş dönemi
  ile indisin toplamından bir eksiktir ve takvim **üç dönemde kapanır**.
- **UI39.** Elde tutma, kohortun girişten $K$ dönem sonra hâlâ okuma üreten abonelerinin oranıdır.
  $K$ dönem sonrası takvimin dışına düşüyorsa oran **gözlenemez**.
- **UI40.** Gözlenemeyen aboneye iki kural uygulanabilir: **sıfır sayan** kural onu elde
  tutulmamış sayar, **dışlayan** kural onu paydadan çıkarır.
- **UI41.** Oynama payı **geri koyarak örneklemeyle** üretilir: kohort listesi 1.000 kez yeniden
  çekilir.
- **UI42.** Okuma yöntemi alanı da **kurgudur** ve iki ilişkiyi birlikte taşır: uzaktan okuma geç
  dönemlerde yaygınlaşmıştır ve kesintisi daha azdır.

## Gözlem Penceresi Kohortu Keser

Takvim üç dönemde kapanıyor. Üçüncü dönemde ağa katılan bir abone için "bir dönem sonra hâlâ
okunabiliyor mu" sorusunun cevabı kümede yoktur. Bu abone elde tutulamamış değildir; **henüz
ölçülmemiştir**.

```python
# kohort.py — MODELDIR. K03'un kurgu kumesi ayni tohumla uretilir. Giris haftasi
# alani da KURGUDUR: olcum agi bolgelere ayni anda ulasmamistir, bu yuzden giris
# donemi dagilimi bolgeye baglidir. Okuma indisi girisden sonraki donemi verir;
# takvim donemi = giris donemi + indis - 1 ve takvim uc donemde kapanir.
import math

TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF
BOLGE = [("kuzey", 0.28, 21), ("guney", 0.22, 17), ("dogu", 0.18, 26),
         ("bati", 0.14, 14), ("merkez", 0.18, 23)]
GIRIS = {"dogu": [0.60, 0.28, 0.12], "merkez": [0.52, 0.30, 0.18],
         "kuzey": [0.40, 0.34, 0.26], "guney": [0.28, 0.36, 0.36],
         "bati": [0.16, 0.32, 0.52]}


def uretec(t):
    x = ((t ^ (t >> 16)) * 2246822507) & M32
    x = ((x ^ (x >> 13)) * 3266489909) & M32
    s = [(x ^ (x >> 16)) & M32]

    def sonraki():
        s[0] = (s[0] * 1664525 + 1013904223) & M32
        return s[0] / 4294967296
    return sonraki


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


ABONE, ELENEN = [], []
for i in range(HAM):
    r = uretec(TOHUM + i)
    b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])]
    ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05])
    ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17])
    (ELENEN if r() < 0.046 else ABONE).append(
        {"abone_no": 10001 + i, "bolge": b[0], "taban": b[2]})
GECERLI = {k["abone_no"] for k 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"] in GECERLI:
            OKUMA.setdefault(k["abone_no"], []).append(t)
        r()

KATILAN = []
for k in ABONE:
    if k["abone_no"] not in OKUMA:
        continue
    r = uretec(TOHUM + 61000 + k["abone_no"])
    e = ayrik(r(), GIRIS[k["bolge"]])
    hafta = e * 13 + 1 + int(r() * 13)
    KATILAN.append({"no": k["abone_no"], "bolge": k["bolge"], "hafta": hafta,
                    "kohort": e + 1, "blok": (hafta - 1) // 5 + 1,
                    "n": len(OKUMA[k["abone_no"]])})

PENCERE = 3


def gozlenebilir(x, K):
    """Kohortun K donem sonrasi uc donemlik takvimin icinde kaliyor mu."""
    return x["kohort"] + K <= PENCERE


def tutuldu(x, K):
    return x["n"] >= K + 1 and gozlenebilir(x, K)


def oran(alt, K, kural):
    pay = alt if kural == "sifir sayan" else [x for x in alt if gozlenebilir(x, K)]
    if not pay:
        return None, 0
    return sum(1 for x in pay if tutuldu(x, K)) / len(pay), len(pay)


print(f"kurgu kume (tohum {TOHUM}): {len(ABONE)} abone, "
      f"{sum(len(v) for v in OKUMA.values())} okuma")
print("giris kohortu (donem): " + ", ".join(
    f"{k}: {sum(1 for x in KATILAN if x['kohort'] == k)}" for k in (1, 2, 3))
    + f"   (en az bir okumasi olan {len(KATILAN)} abone)")
print(f"uc donemlik pencerenin disinda kalan okuma: "
      f"{sum(max(0, x['kohort'] + x['n'] - 1 - PENCERE) for x in KATILAN)}"
      f" / {sum(x['n'] for x in KATILAN)}")

for K in (1, 2):
    print(f"\nelde tutma (girisden {K} donem sonra)")
    print("kohort      n   gozlenebilir   sifir sayan   dislayan")
    for koh in (1, 2, 3):
        alt = [x for x in KATILAN if x["kohort"] == koh]
        o1, n1 = oran(alt, K, "sifir sayan")
        o2, n2 = oran(alt, K, "dislayan")
        print(f"{koh:>6} {len(alt):>6} {n2:>14}   {o1:>11.3f}   "
              + (f"{o2:>8.3f}" if o2 is not None else f"{'--':>8}"))
    o1, _ = oran(KATILAN, K, "sifir sayan")
    o2, n2 = oran(KATILAN, K, "dislayan")
    print(f"{'toplu':>6} {len(KATILAN):>6} {n2:>14}   {o1:>11.3f}   {o2:>8.3f}")
```

```
kurgu kume (tohum 20260218): 1329 abone, 3199 okuma
giris kohortu (donem): 1: 488, 2: 412, 3: 360   (en az bir okumasi olan 1260 abone)
uc donemlik pencerenin disinda kalan okuma: 843 / 3199

elde tutma (girisden 1 donem sonra)
kohort      n   gozlenebilir   sifir sayan   dislayan
     1    488            488         0.871      0.871
     2    412            412         0.862      0.862
     3    360              0         0.000         --
 toplu   1260            900         0.619      0.867

elde tutma (girisden 2 donem sonra)
kohort      n   gozlenebilir   sifir sayan   dislayan
     1    488            488         0.648      0.648
     2    412              0         0.000         --
     3    360              0         0.000         --
 toplu   1260            488         0.251      0.648
```

Rapora girecek sayı, bir dönemlik elde tutma için 0,619 mu 0,867 mi. İkisi de aynı kümeden ve
aynı tanımdan çıkıyor; ayrıldıkları tek yer, gözlenemeyen 360 abonenin ne sayıldığı. Sıfır sayan
kural onları elde tutulmamış kabul ediyor ve oranı 0,248 aşağı çekiyor. İki dönemlik elde tutmada
fark daha da büyük: 0,251 ile 0,648.

Gözlenemeyen aboneyi sıfır saymak bir ölçüm değil bir varsayımdır ve bu varsayım kümede
karşılanmıyor. Kohort 3'ün 360 abonesi için sonraki dönemin okuması **hiç toplanmamıştır**;
toplanmış olsaydı ilk iki kohortun 0,871 ve 0,862 oranlarına yakın bir sayı vermesi beklenir.

Üçüncü satır bu kesilmenin boyutunu veriyor: 3.199 okumanın 843'ü üç dönemlik takvimin dışına
düşüyor. Kohort tanımı kümeyi kesiyor ve kesilen parça küçük değil.

## Giriş Penceresi Kohort Sayısını Değiştirir

Kohortun ikinci kararı giriş penceresinin genişliğidir. Dönem yerine beş haftalık bloklar
alınırsa aynı aboneler sekiz kohorta dağılır. Her kohortun oranının yanına payı da basılır.

```python

# Giris penceresi degisince ayni kumeden kac ayri oran cikiyor.
ORNEKLEME = 1000
rs = uretec(TOHUM + 44000)


def oran_araligi(alt, K):
    """Geri koyarak ornekleme: kohort listesi 1.000 kez yeniden cekilir."""
    n, cekilen = len(alt), []
    for _ in range(ORNEKLEME):
        cekilen.append(sum(1 for _ in range(n) if tutuldu(alt[int(rs() * n)], K)) / n)
    cekilen.sort()
    return cekilen[24], cekilen[974]


def tara(alan, ad):
    anahtarlar = sorted({x[alan] for x in KATILAN})
    print(f"\ngiris penceresi: {ad} -> {len(anahtarlar)} kohort   "
          "(dislayan kural, 1 donem)")
    print("kohort      n   elde tutma   oynama payi          genislik")
    genislikler, oranlar = [], []
    for a in anahtarlar:
        alt = [x for x in KATILAN if x[alan] == a and gozlenebilir(x, 1)]
        if len(alt) < 10:
            print(f"{a:>6} {len(alt):>6}   {'gozlenemez':>10}")
            continue
        o = sum(1 for x in alt if tutuldu(x, 1)) / len(alt)
        d, u = oran_araligi(alt, 1)
        genislikler.append(u - d)
        oranlar.append(o)
        print(f"{a:>6} {len(alt):>6}   {o:>10.3f}   [{d:.3f}, {u:.3f}]  {u - d:>10.3f}")
    print(f"  oran acikligi {max(oranlar) - min(oranlar):.3f}, "
          f"en dar pay {min(genislikler):.3f}, en genis pay {max(genislikler):.3f}")
    return oranlar


d3 = tara("kohort", "donem (13 hafta)")
d8 = tara("blok", "bes hafta")
print(f"\nayni kumeden cikan elde tutma orani sayisi: {len(d3)} ve {len(d8)}")
print(f"donem tanimiyla aralik {min(d3):.3f} - {max(d3):.3f}, "
      f"bes haftalik tanimla {min(d8):.3f} - {max(d8):.3f}")
```

```

giris penceresi: donem (13 hafta) -> 3 kohort   (dislayan kural, 1 donem)
kohort      n   elde tutma   oynama payi          genislik
     1    488        0.871   [0.840, 0.898]       0.057
     2    412        0.862   [0.828, 0.896]       0.068
     3      0   gozlenemez
  oran acikligi 0.009, en dar pay 0.057, en genis pay 0.068

giris penceresi: bes hafta -> 8 kohort   (dislayan kural, 1 donem)
kohort      n   elde tutma   oynama payi          genislik
     1    181        0.878   [0.829, 0.923]       0.094
     2    185        0.854   [0.805, 0.903]       0.097
     3    184        0.891   [0.848, 0.935]       0.087
     4    174        0.856   [0.805, 0.908]       0.103
     5    155        0.852   [0.800, 0.903]       0.103
     6     21        0.857   [0.667, 1.000]       0.333
     7      0   gozlenemez
     8      0   gozlenemez
  oran acikligi 0.040, en dar pay 0.087, en genis pay 0.333

ayni kumeden cikan elde tutma orani sayisi: 2 ve 6
donem tanimiyla aralik 0.862 - 0.871, bes haftalik tanimla 0.852 - 0.891
```

Giriş penceresi daraldığında raporlanabilir oran sayısı 2'den 6'ya çıkıyor ve oranlar arasındaki
açıklık 0,009'dan 0,040'a genişliyor. Bir kohort matrisine bakan kişi bu genişlemeyi bir örüntü
diye okuyabilir: üçüncü blok 0,891, beşinci blok 0,852, aradaki 4 puanlık düşüş bir eğilim gibi
görünür.

Payların sütunu bu okumayı kapatıyor. En dar oynama payı 0,087 genişliğinde; altı blok arasındaki
0,040'lık açıklığın tamamı **tek bir kohortun payının içine sığıyor**. Blokların ikişer ikişer
farkları da payların içinde kalıyor. İnce kohort tanımı yeni bilgi üretmedi, aynı bilgiyi daha çok
sayıya böldü ve her sayının payını büyüttü.

Altıncı blok bunun uç örneği. Yirmi bir gözlenebilir aboneye dayanan oran 0,857, payı ise
[0,667, 1,000]; genişliği 0,333, yani beş kohortun payının üç katından fazla. Yedinci ve sekizinci
bloklar tümüyle gözlem penceresinin dışında kalıyor ve hiç oran üretmiyor. Kohort tanımı
inceldikçe gözlenemeyen kohort sayısı da artıyor.

## Toplulaştırılmış Oran ve Kohortların Oranı

Kohortun ne işe yaradığı, toplulaştırılmış bir oranın yanına konduğunda görünür. Kümede iki okuma
yöntemi var ve huninin iki adımı şudur: kohorta giriş, sonraki dönemde okuma.

```python

# Okuma yontemi alani da KURGUDUR ve iki iliskiyi birlikte tasir: uzaktan okuma
# gec donemlerde yayginlasmistir ve kesintisi daha azdir.
YONTEM_TABAN = {1: 0.28, 2: 0.55, 3: 0.80}
for x in KATILAN:
    r = uretec(TOHUM + 71000 + x["no"])
    p = YONTEM_TABAN[x["kohort"]] + (0.10 if x["n"] >= 2 else -0.10)
    x["yontem"] = "uzaktan" if r() < p else "yerinde"

YON = ("yerinde", "uzaktan")


def fark_araligi(a, b, K):
    na, nb, cekilen = len(a), len(b), []
    for _ in range(ORNEKLEME):
        oa = sum(1 for _ in range(na) if tutuldu(a[int(rs() * na)], K)) / na
        ob = sum(1 for _ in range(nb) if tutuldu(b[int(rs() * nb)], K)) / nb
        cekilen.append(ob - oa)
    cekilen.sort()
    return cekilen[24], cekilen[974]


print("huni: kohorta giris -> sonraki donemde okuma")
print("\nkohort   yerinde okuma      uzaktan okuma      fark     oynama payi")
for koh in (1, 2, 3):
    alt = [x for x in KATILAN if x["kohort"] == koh]
    a = [x for x in alt if x["yontem"] == "yerinde"]
    b = [x for x in alt if x["yontem"] == "uzaktan"]
    if not gozlenebilir(alt[0], 1):
        print(f"{koh:>6}   {'--':>5} ({len(a):>3})       {'--':>5} ({len(b):>3})"
              f"        --   gozlenemez")
        continue
    oa = sum(1 for x in a if tutuldu(x, 1)) / len(a)
    ob = sum(1 for x in b if tutuldu(x, 1)) / len(b)
    d, u = fark_araligi(a, b, 1)
    print(f"{koh:>6}   {oa:.3f} ({len(a):>3})       {ob:.3f} ({len(b):>3})"
          f"    {ob - oa:>+.3f}   [{d:+.3f}, {u:+.3f}]")
a = [x for x in KATILAN if x["yontem"] == "yerinde"]
b = [x for x in KATILAN if x["yontem"] == "uzaktan"]
oa = sum(1 for x in a if tutuldu(x, 1)) / len(a)
ob = sum(1 for x in b if tutuldu(x, 1)) / len(b)
d, u = fark_araligi(a, b, 1)
print(f"{'toplu':>6}   {oa:.3f} ({len(a):>3})       {ob:.3f} ({len(b):>3})"
      f"    {ob - oa:>+.3f}   [{d:+.3f}, {u:+.3f}]")

print("\nyontemin kohort bilesimi (satir yuzdesi)")
for y in YON:
    alt = [x for x in KATILAN if x["yontem"] == y]
    print(f"  {y:<8} " + "  ".join(
        f"kohort {k}: {sum(1 for x in alt if x['kohort'] == k) / len(alt):.3f}"
        for k in (1, 2, 3)))
```

```
huni: kohorta giris -> sonraki donemde okuma

kohort   yerinde okuma      uzaktan okuma      fark     oynama payi
     1   0.843 (325)       0.926 (163)    +0.083   [+0.028, +0.139]
     2   0.844 (154)       0.872 (258)    +0.028   [-0.041, +0.099]
     3      -- ( 56)          -- (304)        --   gozlenemez
 toplu   0.755 (535)       0.519 (725)    -0.237   [-0.284, -0.184]

yontemin kohort bilesimi (satir yuzdesi)
  yerinde  kohort 1: 0.607  kohort 2: 0.288  kohort 3: 0.105
  uzaktan  kohort 1: 0.225  kohort 2: 0.356  kohort 3: 0.419
```

Toplulaştırılmış satır tek bir cümle söylüyor: uzaktan okunan sayaçlarda elde tutma 0,237 puan
düşük ve payı [-0,284, -0,184], sıfırdan uzakta. Bu sayı ve bu pay, kursun kuralının istediği
biçimde yazılmıştır ve yanlıştır.

Kohort satırları tersini gösteriyor. Birinci kohortta uzaktan okuma 0,083 puan **önde** ve payı
[+0,028, +0,139], sıfırı içermiyor. İkinci kohortta 0,028 puan önde, payı sıfırı içeriyor.
Üçüncü kohort gözlenemiyor. Toplulaştırılmış oranın gösterdiği yönü **hiçbir kohort
göstermiyor**: ikisi tersini söylüyor, biri hiçbir şey söylemiyor.

Bu olguya **toplulaştırma tersine dönmesi** denir ve mekanizması son tabloda duruyor. Yerinde
okunan sayaçların yüzde 60,7'si birinci kohortta; uzaktan okunanların yüzde 41,9'u üçüncü
kohortta. Üçüncü kohort gözlem penceresi yüzünden sıfır sayılıyor, dolayısıyla uzaktan okumanın
toplulaştırılmış oranı ağırlıklı olarak **ölçülememiş** abonelerden geliyor. İki yöntemin farkı
değil, iki yöntemin kohort bileşimi ölçülmüştür.

Toplulaştırılmış bir oran, kohortlar arasında oran farkı **ve** bileşim farkı varsa hiçbir
kohortu tarif etmez. Bileşim yazılmadan raporlanan bir toplulaştırılmış oran, bir ölçüm değil bir
ortalama alma kararıdır.

## Özet

- Gözlenemeyen kohorta uygulanan kural aynı kümeden iki oran çıkarır: bir dönemlik elde tutma
  sıfır sayan kuralla 0,619, dışlayan kuralla 0,867; iki dönemlikte 0,251 ile 0,648.
- Üç dönemlik gözlem penceresinin dışında 3.199 okumanın 843'ü kalır; kohort tanımı kümeyi keser.
- Giriş penceresi dönemden beş haftaya inince raporlanabilir oran sayısı 2'den 6'ya, oran açıklığı
  0,009'dan 0,040'a çıkar; en dar oynama payı 0,087 olduğu için açıklığın tamamı tek bir kohortun
  payının içine sığar.
- Yirmi bir aboneye dayanan altıncı blokta oran 0,857, payı [0,667, 1,000] ve genişliği 0,333;
  yedinci ve sekizinci bloklar tümüyle gözlem penceresinin dışındadır.
- Toplulaştırma tersine dönmesi: toplulaştırılmış fark -0,237 ve payı sıfırdan uzakken,
  gözlenebilir iki kohortta fark +0,083 ve +0,028'dir. Yerinde okunanların yüzde 60,7'si birinci,
  uzaktan okunanların yüzde 41,9'u üçüncü kohorttadır.

## Sonraki Adım

Üç derste sayının yanına payı yazıldı ve payı büyüten üç kaynak sayıldı: bileşim sayısı, modelde
bulunmayan değişken, kohort tanımı. Üçünde de küme verilmiş kabul edildi. Kursun son dersi bu
kabulü kaldırır: küme zaten okunabilmiş sayaçlardan ve en az bir okuma üretmiş abonelerden
oluşuyor, yani ölçülen şey ağın kendisi değil ağın görünen kısmı. Aynı derste gürültüden kaç bulgu
üretilebildiği sayılır ve bu sayı beklenen değerle karşılaştırılır.
