Ders 03 / 13
İki Değişkenli İnceleme
Tüketim sütunu dört sütunla eşleştirilir ve her katsayının yanına payı basılır: hane kişi sayısıyla +0,010 ve memnuniyetle −0,010 katsayıları 2.000 karıştırmanın 1.189 ve 1.154'ünde aşılır, dönem sırasıyla çıkan −0,111 hiçbirinde aşılmaz, tarife basamağıyla çıkan +0,883 ise bir keşif değil bir tanımdır. Aynı +0,600 katsayısını veren üç kurgu ilişki yan yana konur: doğrusal olanın dilim ortalamaları 6,6'dan 24,9'a düzgün çıkar, eğrisel olanınki 39,8'e çıkıp 37,1'e döner, kaldıraçlı olanınki 20 civarında sabit kalır ve tek bir uç nokta çıkarıldığında katsayı −0,057'ye iner. Bölge ile tarife basamağının çapraz tablosu batıda dördüncü basamağın hiç görünmediğini, doğuda küme payının üç katına çıktığını sayar. Sıralayıcı ölçekte kodlama değiştiğinde katsayı memnuniyette mutlak değerce yüzde 79 oynar, sıra korelasyonu −0,0102'de durur.
İçindekiler
Önceki ders tek bir sütuna baktı ve biçimini beş sayı ile aralık sayımlarıyla yazdı. Soruların çoğu ise iki sütun ister: tüketim hane büyüklüğüyle birlikte mi artıyor, dönem ilerledikçe düşüyor mu, memnuniyet düzeyiyle bir bağı var mı. İki sütun birlikte incelendiğinde yeni bir özet çıkar — korelasyon katsayısı — ve o da bir yığın sayıyı tek sayıya sıkıştırır.
Bu dersin ölçüsü katsayının göremediği örüntüdür. Aynı katsayıyı veren üç ayrı ilişki kurulur, üçü de aynı sayıyla raporlanır ve aradaki farkın katsayıya hiç yansımadığı gösterilir.
- EA11. İki değişkenli inceleme (bivariate) iki sütunu birlikte ele alır. Korelasyon katsayısı ortak değişimin iki ayrı değişimin çarpımına oranıdır ve yalnızca doğrusal birlikte değişimi ölçer.
- EA12. Katsayının yanına payı yazılır: sütunlardan biri rastgele yeniden dizilir ve aynı büyüklükte bir katsayının kaç koşumda bir ortaya çıktığı sayılır.
- EA13. Katsayı saçılım grafiğinin (scatter plot) yerini tutmaz. Saçılım burada çizilmez, dilim ortalamalarıyla basılır: sürücü sütun beş eşit parçaya bölünür ve her parçada ikinci sütunun ortalaması yazılır.
- EA14. Çapraz tablo (cross tabulation) iki kategorik sütunun birlikte sayımıdır. Sınıflayıcı ölçekte korelasyon katsayısı tanımlı değildir; ilişki hücre sayımlarından okunur.
- EA15. Sıra korelasyonu yalnızca sıraya bakar. Sıralayıcı ölçekte düzeylere verilen sayılar bir kodlama kararıdır — ölçek tanımları Veri Analitiğine Giriş kursunda kuruldu ve burada tekrarlanmaz. Katsayı bu karardan etkilenir, sıra korelasyonu etkilenmez.
Katsayı ve Payı
# kesif.py — MODELDIR: K03 ve K04'un kurgu olcum agi ayni tohumla yeniden # uretilir. Kume kurgudur; hicbir gercek abone, sayac ya da bolge temsil edilmez. import math TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF DONEM = ["2026-01", "2026-02", "2026-03"] TARIFE = [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): """Dogrusal eslemeli uretec: tohum koda yazilidir, cikti kosumdan kosuma ayni.""" 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 _abone, _elenen = [], [] for i in range(HAM): r = uretec(TOHUM + i) b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])] k = {"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(k) _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, "hane_kisi": k["hane_kisi"], "memnuniyet": k["memnuniyet"], "basamak": 1 if t < TARIFE[0] else 2 if t < TARIFE[1] else 3 if t < TARIFE[2] else 4}) r() def ort(v: list[float]) -> float: return sum(v) / len(v) def kor(x: list[float], y: list[float]) -> float: """Korelasyon katsayisi: ortak degisimin iki ayri degisimin carpimina orani.""" mx, my = ort(x), ort(y) sx = math.sqrt(sum((a - mx) ** 2 for a in x)) sy = math.sqrt(sum((b - my) ** 2 for b in y)) return sum((a - mx) * (b - my) for a, b in zip(x, y)) / (sx * sy) def siralar(v: list[float]) -> list[float]: """Esit degerler ortalama sira alir; siralayici olcegin gerektirdigi budur.""" yer: dict[float, list[int]] = {} for k, i in enumerate(sorted(range(len(v)), key=lambda j: v[j])): yer.setdefault(v[i], []).append(k + 1) return [ort(yer[x]) for x in v] def sira_kor(x: list[float], y: list[float]) -> float: return kor(siralar(x), siralar(y)) KOSUM = 2000 ESIK = 1e-9 # ayni katsayi iki yoldan hesaplaninca son basamak oynar def kor_payi(x: list[float], y: list[float], tohum: int) -> tuple[int, float]: """y sutunu rastgele yeniden dizilir, katsayi her kosumda yeniden olculur.""" r, gozlenen = uretec(tohum), kor(x, y) mx, my = ort(x), ort(y) bol = math.sqrt(sum((a - mx) ** 2 for a in x) * sum((b - my) ** 2 for b in y)) dx, dy = [a - mx for a in x], [b - my for b in y] asan, en_uc = 0, 0.0 for _ in range(KOSUM): h = dy[:] for i in range(len(h) - 1, 0, -1): j = int(r() * (i + 1)) h[i], h[j] = h[j], h[i] c = sum(a * b for a, b in zip(dx, h)) / bol asan += abs(c) >= abs(gozlenen) - ESIK en_uc = max(en_uc, abs(c)) return asan, en_uc TUKETIM = [o["tuketim_m3"] for o in OKUMA] CIFT = [("hane_kisi", [o["hane_kisi"] for o in OKUMA]), ("memnuniyet", [o["memnuniyet"] for o in OKUMA]), ("donem sirasi", [DONEM.index(o["donem"]) for o in OKUMA]), ("basamak", [o["basamak"] for o in OKUMA])] def hiza(w: list[int], sol: int = 1): """Ilk `sol` sutun sola, kalanlar saga yaslanir.""" return lambda h: "".join(str(v).ljust(w[i]) if i < sol else str(v).rjust(w[i]) for i, v in enumerate(h)) y = hiza([26, 7, 11, 12, 10, 8]) print(y(["cift", "n", "katsayi", "sira kats.", "en uc", "asan"])) for i, (ad, v) in enumerate(CIFT): asan, en_uc = kor_payi(TUKETIM, v, TOHUM + 710 + i) print(y([f"tuketim / {ad}", len(v), f"{kor(TUKETIM, v):+.3f}", f"{sira_kor(TUKETIM, v):+.3f}", f"{en_uc:.3f}", asan])) print(f"\n{KOSUM} kosum; en uc = karistirilmis kumelerde gorulen en buyuk katsayi")
cift n katsayi sira kats. en uc asan tuketim / hane_kisi 3199 +0.010 +0.014 0.069 1189 tuketim / memnuniyet 3199 -0.010 -0.010 0.058 1154 tuketim / donem sirasi 3199 -0.111 -0.113 0.061 0 tuketim / basamak 3199 +0.883 +0.813 0.065 0 2000 kosum; en uc = karistirilmis kumelerde gorulen en buyuk katsayi
Yalnız katsayı sütununa bakılırsa ilk iki satır “zayıf ama var olan bir ilişki” gibi okunabilir: +0,010 ve −0,010 sıfır değildir. Pay sütunu bunu kapatıyor. Karıştırılmış kümeler bu büyüklükte bir katsayıyı 2.000 koşumun 1.189’unda ve 1.154’ünde üretiyor. İki satır da gürültüdür.
Üçüncü satır ters yöne gidiyor. Dönem sırası ile tüketim arasındaki −0,111 de küçüktür, ama karıştırılmış kümelerde görülen en büyük katsayı 0,061’dir ve 2.000 koşumun hiçbiri gözlenene ulaşmıyor. Söyleyen şey katsayının büyüklüğü değil, karıştırma dağılımına göre nerede durduğudur.
Dördüncü satır payın da tek başına yetmediğini gösteriyor. Tarife basamağı ile tüketim arasındaki katsayı +0,883’tür ve payı sıfırdır, ama basamak tüketimden hesaplanır: 10, 25 ve 40 m³ sınırları onu belirler. Katsayı burada bir keşfi değil bir tanımı ölçüyor.
Aynı Katsayı, Üç Ayrı İlişki
# ayni_katsayi.py — KURGU: ayni katsayiyi veren uc ayri iliski. Serbest parametre # (gurultu agirligi, uc noktanin uzakligi) hedefe ikiye bolerek oturtulur. N, HEDEF = 557, 0.600 def surucu(tohum: int): r = uretec(tohum) return ([round(4 + 16 * r(), 2) for _ in range(N)], [r() + r() + r() - 1.5 for _ in range(N)]) def ayarla(f, ust: float) -> float: """f(p) katsayiyi verir ve p ile tek yonlu degisir; hedefe ikiye bolunerek yaklasilir.""" alt, artan = 0.0, f(ust) > f(0.0) for _ in range(50): o = (alt + ust) / 2 if (f(o) < HEDEF) == artan: alt = o else: ust = o return (alt + ust) / 2 def karistir(x, taban, gurultu): w = ayarla(lambda p: kor(x, [t + p * g for t, g in zip(taban, gurultu)]), 200.0) return [round(t + w * g, 2) for t, g in zip(taban, gurultu)] x1, g1 = surucu(TOHUM + 801) y1 = karistir(x1, [1.4 * a for a in x1], g1) x2, g2 = surucu(TOHUM + 802) y2 = karistir(x2, [-0.16 * (a - 14.0) ** 2 + 40 for a in x2], g2) # 14 m3'te tepe r3 = uretec(TOHUM + 803) x3 = [round(4 + 16 * r3(), 2) for _ in range(N - 1)] y3 = [round(20 + 9 * (r3() + r3() + r3() - 1.5), 2) for _ in range(N - 1)] uzak = ayarla(lambda k: kor(x3 + [20 + k], y3 + [20 + 3 * k]), 400.0) x3, y3 = x3 + [round(20 + uzak, 2)], y3 + [round(20 + 3 * uzak, 2)] def dilim_ort(x: list[float], y: list[float], d: int = 5) -> list[float]: s = sorted(zip(x, y)) return [ort([b for _, b in s[i * len(s) // d:(i + 1) * len(s) // d]]) for i in range(d)] i_ = hiza([13, 11, 12]) print(i_(["iliski", "katsayi", "sira kats."]) + " dilim ortalamalari (y)") for ad, x, y in [("dogrusal", x1, y1), ("egrisel", x2, y2), ("kaldiracli", x3, y3)]: print(i_([ad, f"{kor(x, y):+.3f}", f"{sira_kor(x, y):+.3f}"]) + " " + " ".join(f"{v:5.1f}" for v in dilim_ort(x, y))) print(f"\nkaldiracli iliskide uc nokta ({x3[-1]}, {y3[-1]}); kalan {N - 1} noktanin " f"x araligi 4-20") print(f"o tek nokta cikarilinca katsayi {kor(x3[:-1], y3[:-1]):+.3f} olur")
iliski katsayi sira kats. dilim ortalamalari (y) dogrusal +0.600 +0.594 6.6 12.6 15.4 21.4 24.9 egrisel +0.600 +0.559 27.8 34.9 38.8 39.8 37.1 kaldiracli +0.600 -0.052 20.1 20.0 19.9 19.4 21.7 kaldiracli iliskide uc nokta (104.4, 273.2); kalan 556 noktanin x araligi 4-20 o tek nokta cikarilinca katsayi -0.057 olur
Üç ilişkinin katsayısı üçüncü basamağa kadar aynıdır ve “korelasyon katsayısı +0,600” cümlesi üçünü birbirinden ayırmaz. Ayıran şey son sütundur: sürücü sütun beş dilime bölünüp her dilimde ikinci sütunun ortalaması yazıldığında üç ayrı örüntü çıkıyor.
Doğrusal ilişkide dilim ortalamaları 6,6’dan 24,9’a düzgün tırmanıyor. Eğrisel ilişkide 27,8’den 39,8’e çıkıp 37,1’e dönüyor: ikinci sütun bir yere kadar artıyor, sonra azalıyor. Katsayı bu dönüşü göremez, çünkü doğrusal birlikte değişimi ölçer ve dönüşün iki yanı birbirini kısmen götürür. Sıra korelasyonu da göremiyor; 0,559 ile 0,594 arasındaki fark tek başına uyarı sayılmaz.
Üçüncü satır en sert olanıdır. Dilim ortalamaları 20,1 — 20,0 — 19,9 — 19,4 çizgisinde duruyor: hiçbir eğilim yok. Katsayıyı tek bir nokta taşıyor — 556 nokta 4 ile 20 arasında dururken biri (104,4, 273,2) konumundadır — ve o nokta çıkarıldığında katsayı −0,057’ye iner. Sıra korelasyonu bunu baştan söylüyor, çünkü sıralama bir noktanın uzaklığını umursamaz.
Ölçünün özeti şudur: katsayı iki boyutlu bir biçimi tek sayıya indirir ve neyi indirdiğini söylemez; beş dilim ortalaması üç ilişkiyi de ayırır.
Kategorik ve Sıralayıcı Sütunlar
# kategorik.py — capraz tablo iki kategorik sutunu birlikte sayar; bolge # siniflayici bir olcektir ve korelasyon katsayisi bu cift icin tanimli degildir. from collections import Counter hucre = Counter((o["bolge"], o["basamak"]) for o in OKUMA) BOLGELER = sorted({o["bolge"] for o in OKUMA}) KADEME = [1, 2, 3, 4] c = hiza([9, 6] + [6] * 4 + [7] * 4) print(c(["bolge", "n"] + [f"b{k}" for k in KADEME] + [f"%b{k}" for k in KADEME])) for b in BOLGELER + ["kume"]: say = [sum(hucre[(x, k)] for x in (BOLGELER if b == "kume" else [b])) for k in KADEME] print(c([b, sum(say)] + say + [f"{100 * s / sum(say):.1f}" for s in say])) # Siralayici olcekte duzeylere verilen sayilar bir karardir: kodlama degisince # katsayi degisir, sira korelasyonu yalnizca siraya baktigi icin degismez. SUTUN = [("basamak", [o["basamak"] for o in OKUMA], [("esit aralik", {1: 1, 2: 2, 3: 3, 4: 4}), ("ikiye katlanan", {1: 1, 2: 2, 3: 4, 4: 8}), ("basamak orta noktasi", {1: 5.0, 2: 17.5, 3: 32.5, 4: 45.0})]), ("memnuniyet", [o["memnuniyet"] for o in OKUMA], [("esit aralik", {d: d for d in range(1, 6)}), ("ikiye katlanan", {1: 1, 2: 2, 3: 4, 4: 8, 5: 16})])] o_ = hiza([13, 23, 12, 12], 2) print("\n" + o_(["sutun", "kodlama", "katsayi", "sira kats."])) for ad_s, sut, kodlar in SUTUN: k = [kor(TUKETIM, [m[d] for d in sut]) for _, m in kodlar] for (ad, m), deger in zip(kodlar, k): print(o_([ad_s, ad, f"{deger:+.4f}", f"{sira_kor(TUKETIM, [m[d] for d in sut]):+.4f}"])) oynama = 100 * (max(map(abs, k)) / min(map(abs, k)) - 1) print(f"{ad_s}: katsayi mutlak degerde {oynama:.0f} yuzde oynadi, " f"sira korelasyonu oynamadi")
bolge n b1 b2 b3 b4 %b1 %b2 %b3 %b4 bati 476 88 377 11 0 18.5 79.2 2.3 0.0 dogu 557 21 281 225 30 3.8 50.4 40.4 5.4 guney 645 59 538 48 0 9.1 83.4 7.4 0.0 kuzey 921 42 661 210 8 4.6 71.8 22.8 0.9 merkez 600 30 352 198 20 5.0 58.7 33.0 3.3 kume 3199 240 2209 692 58 7.5 69.1 21.6 1.8 sutun kodlama katsayi sira kats. basamak esit aralik +0.8832 +0.8125 basamak ikiye katlanan +0.8417 +0.8125 basamak basamak orta noktasi +0.8800 +0.8125 basamak: katsayi mutlak degerde 5 yuzde oynadi, sira korelasyonu oynamadi memnuniyet esit aralik -0.0103 -0.0102 memnuniyet ikiye katlanan -0.0184 -0.0102 memnuniyet: katsayi mutlak degerde 79 yuzde oynadi, sira korelasyonu oynamadi
Bölge sınıflayıcı bir ölçektir: kuzey ile doğu arasında sıra yoktur ve korelasyon katsayısı hesaplanamaz. İlişki hücre sayımlarından okunur. Batıda 476 satırın yüzde 79,2’si ikinci basamaktadır, dördüncü basamakta hiç satır yoktur; doğuda 557 satırın yüzde 5,4’ü dördüncü basamaktadır. Küme genelinde bu pay yüzde 1,8’dir, yani doğunun payı üç katına yakındır.
Tablonun kendi payı hücre sayımlarında görünür. Kuzeyin dördüncü basamağında 8, batının üçüncüsünde 11 satır vardır; 8 satırlık bir hücrede tek bir satır oranı sekizde bir kadar oynatır. Yüzdenin yanında kaç gözleme dayandığı yazılmadıkça tablo okunamaz.
Alt tablo sıralayıcı ölçeğin kararını ölçüyor. Tarife basamağı 1, 2, 3, 4 diye numaralandırılabilir; ikiye katlanan bir dizi de, basamakların orta noktaları da aynı sıralamayı verir. Katsayı yine de 0,8832 — 0,8417 — 0,8800 olarak değişir. Memnuniyette etki daha büyüktür: mutlak değerce yüzde 79. Sıra korelasyonu iki sütunda da yerinde kalır.
Nedeni ölçeğin tanımındadır. Sıralayıcı ölçekte düzeyler arasındaki uzaklık ölçülmemiştir, yalnızca sıra bilinir. Katsayı düzey sayılarını çarptığı için birinci ile ikinci basamak arasındaki açıklığı üçüncü ile dördüncü arasındakine eşit sayar; ölçek bunu desteklemez. Sıra korelasyonu kodlamadan bağımsızdır.
Özet
- Katsayı payıyla okunur: +0,010 ve −0,010 katsayıları 2.000 karıştırmanın 1.189 ve 1.154’ünde aşılır, −0,111 hiçbirinde aşılmaz; büyüklük tek başına ayırt etmez.
- Payı sıfır olan katsayı da bulgu olmayabilir: +0,883, basamak tüketimden hesaplandığı için bir tanımı ölçer.
- Aynı +0,600 katsayısını veren üç ilişki dilim ortalamalarıyla ayrışır: 6,6’dan 24,9’a artış, 39,8’e çıkıp 37,1’e dönen eğri ve 20 civarında düz çizgi.
- Kaldıraçlı ilişkide katsayıyı tek bir nokta taşır; o nokta çıkınca katsayı −0,057’ye iner.
- Sıralayıcı ölçekte kodlama katsayıyı oynatır — memnuniyette mutlak değerce yüzde 79 — sıra korelasyonu oynamaz.
Sonraki Adım
Bu ders tek bir çifte baktı ve katsayısına payını yazdı. Gerçek bir kümede çift sayısı ikide kalmaz: dört sayısal sütun altı çift, altı sütun on beş çift üretir. Her çifte ayrı bakmak her seferinde yeni bir soru sormaktır ve sorular çoğaldıkça rastlantının en az birinde yüksek katsayı üretme şansı büyür. Sonraki ders korelasyon matrisini kurar, tümüyle bağımsız üretilmiş sütunlarda kaç çiftin yüksek katsayı verdiğini sayar ve kaç bileşenin değişimin ne kadarını taşıdığını hesaplar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.