Think Stats kitabının üçüncü baskısını Bookshop.org ve Amazon üzerinden edinebilirsiniz (bunlar satış ortaklığı bağlantılarıdır). Ücretsiz çevrimiçi sürümü beğeniyorsanız bana bir kahve ısmarlamayı düşünebilirsiniz.

9. Hipotez testi#

Bu kitapta incelediğimiz veri kümelerinde insan ve penguen grupları arasındaki farkları, değişkenler arasındaki korelasyonları ve regresyon doğrularının eğimlerini gördük. Bu tür sonuçlara gözlenen etkiler denir; çünkü doğrudan gözleyemediğimiz evrendeki gerçek etkilerin aksine, bunları örneklemde gözleriz. Örneklemde bir etki gözlediğimizde bunun daha geniş evrende de bulunmasının olası mı, yoksa örneklemde şans eseri ortaya çıkmış mı olduğunu düşünmeliyiz.

Bu soruyu Fisher’ın sıfır hipotezi testi, Neyman–Pearson karar kuramı ve Bayesçi hipotez testi gibi çeşitli yollarla ifade edebiliriz. Burada uygulamada sık kullanılan bu yaklaşımların bir karışımını sunuyorum.

Bu notebook’u Colab’da çalıştırmak için buraya tıklayın.

Kod hücresi içeriğini gizle

from os.path import basename, exists


def download(url):
    filename = basename(url)
    if not exists(filename):
        from urllib.request import urlretrieve

        local, _ = urlretrieve(url, filename)
        print("İndirildi: " + local)


download("https://github.com/TerekliTahaBerk/thinkstatstr/raw/v3/nb/thinkstats.py")

Kod hücresi içeriğini gizle

try:
    import empiricaldist
except ImportError:
    %pip install empiricaldist

Kod hücresi içeriğini gizle

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from thinkstats import decorate

9.1. Yazı tura#

David MacKay’in Information Theory, Inference, and Learning Algorithms kitabındaki bir örneğe dayanan basit bir örnekle başlayacağız.

Avro madeni paraları 2002’de kullanıma girdiğinde meraklı bir koleksiyoncu, Belçika’ya ait bir avroluk parayı kenarı üzerinde 250 kez döndürdü; paranın 140 kez yazı, 110 kez tura geldiğini kaydetti. Para kusursuz dengeliyse yalnızca 125 yazı bekleriz; dolayısıyla veriler paranın yanlı olduğunu düşündürür. Öte yandan her seferinde tam 125 yazı beklemeyiz. Para aslında adil olabilir ve beklenen değerden gözlenen sapma şanstan kaynaklanabilir. Bunun makul olup olmadığını görmek için hipotez testi yapabiliriz.

Para adilse gözlenen sayı ile beklenen sayı arasındaki mutlak farkı hesaplamak için aşağıdaki işlevi kullanacağız.

n = 250
p = 0.5


def abs_deviation(heads):
    expected = n * p
    return np.abs(heads - expected)

Gözlenen veride bu sapma 15’tir.

heads = 140
tails = 110

observed_stat = abs_deviation(heads)
observed_stat
np.float64(15.0)

Para gerçekten adilse eşit olasılıkla 'H' ya da 'T' içeren rastgele bir dizi üretip 'H' sayısını sayarak para döndürme deneyini simüle edebiliriz.

def simulate_flips():
    flips = np.random.choice(["H", "T"], size=n)
    heads = np.sum(flips == "H")
    return heads

Bu işlevi her çağırdığımızda simüle edilmiş bir deney sonucu elde ederiz.

np.random.seed(1)
simulate_flips()
np.int64(119)

Aşağıdaki döngü deneyi çok kez simüle eder, her birinin sapmasını hesaplar ve sonuçları bir liste üreteciyle toplar.

simulated_stats = [abs_deviation(simulate_flips()) for i in range(10001)]

Sonuç, paranın adil olduğu varsayımı altındaki sapma dağılımından bir örneklemdir. Değerlerin dağılımı şöyle görünür.

from empiricaldist import Pmf

pmf_effects = Pmf.from_seq(simulated_stats)
pmf_effects.bar()

decorate(xlabel="Mutlak sapma", ylabel="PMF")
_images/315335ca0bbae2cf5476b6a5f4ef8a65384bddd59fdba2122ba9118fc373c8b2.png

0’a yakın değerler en yaygın, 10’dan büyük değerler daha seyrektir. Gözlenen sapmanın 15 olduğunu anımsarsak bu büyüklükteki sapmaların nadir, ancak olanaksız olmadığını görürüz. Bu örnekte simüle edilmiş sonuçlar zamanın yaklaşık %7,1’inde 15’e eşit ya da daha büyüktür.

(np.array(simulated_stats) >= 15).mean() * 100
np.float64(7.079292070792921)

Dolayısıyla para adilse yalnızca şans sonucu, gördüğümüz kadar büyük bir sapmayı zamanın yaklaşık %7,1’inde bekleriz.

Bu büyüklükte bir etkinin yaygın olmadığı, ancak para adil olsa bile kesinlikle olanaksız olmadığı sonucuna varabiliriz. Bu deneye dayanarak paranın adil olma olasılığını eleyemeyiz.

Bu örnek istatistiksel hipotez testinin mantığını gösterir.

  • 250 döndürmede 140 yazı gözlemiyle ve paranın yanlı olduğu, yani yazı olasılığının %50’den farklı olduğu hipoteziyle başladık.

  • Gözlenen etkinin büyüklüğünü nicelleştiren bir test istatistiği seçtik. Burada bu, beklenen sonuçtan mutlak sapmadır.

  • Gözlenen etkinin şanstan kaynaklandığı varsayımına dayanan bir model olan sıfır hipotezini tanımladık. Burada sıfır hipotezi paranın adil olmasıdır.

  • Ardından sıfır hipotezi doğruysa gözlenen etkiyi görme olasılığı olan p-değerini hesapladık. Burada p-değeri, 15 veya daha büyük sapma olasılığıdır.

Son adım sonucu yorumlamaktır. p-değeri küçükse etkinin yalnızca şanstan kaynaklanmış olma olasılığının düşük olduğu; büyükse etkinin şansla açıklanabileceği sonucuna varırız. Bu örnekteki gibi arada bir yerdeyse etkinin yalnızca şanstan kaynaklanmış olması pek olası değildir, ancak bu olasılığı da eleyemeyiz.

Tüm hipotez testleri bu öğelere dayanır: test istatistiği, sıfır hipotezi ve p-değeri.

9.2. Ortalama farkı testi#

NSFG verilerinde ilk bebeklerin ortalama gebelik süresinin sonraki bebeklerden biraz daha uzun olduğunu gördük. Şimdi bu farkın şanstan kaynaklanıp kaynaklanamayacağına bakalım.

Aşağıdaki hücreler verileri indirir ve okumak için gereken statadict paketini kurar.

download("https://github.com/TerekliTahaBerk/thinkstatstr/raw/v3/nb/nsfg.py")
download("https://github.com/TerekliTahaBerk/thinkstatstr/raw/v3/data/2002FemPreg.dct")
download("https://github.com/TerekliTahaBerk/thinkstatstr/raw/v3/data/2002FemPreg.dat.gz")
try:
    import statadict
except ImportError:
    %pip install statadict

get_nsfg_groups işlevi verileri okur, canlı doğumları seçer ve bunları ilk bebekler ile diğerleri olarak gruplar.

from nsfg import get_nsfg_groups

live, firsts, others = get_nsfg_groups()

Şimdi iki grubun hafta cinsinden gebelik sürelerini seçebiliriz.

data = firsts["prglngth"].values, others["prglngth"].values

Aşağıdaki işlev verileri iki dizilik bir demet olarak alır ve ortalamalar arasındaki mutlak farkı hesaplar.

def abs_diff_means(data):
    group1, group2 = data
    diff = np.mean(group1) - np.mean(group2)
    return np.abs(diff)

İlk bebekler ile diğerleri arasında gözlenen gebelik süresi farkı 0,078 haftadır.

observed_diff = abs_diff_means(data)
observed_diff
np.float64(0.07803726677754952)

Test edeceğimiz hipotez, ilk bebekler ile diğerleri arasında gebelik süresi farkı olup olmadığıdır. Sıfır hipotezi, gebelik sürelerinin gerçekte iki grup için aynı ve gözlenen farkın şanstan kaynaklandığıdır. İki grup için dağılımlar aynıysa bunları tek bir havuzda birleştirebiliriz. Deneyi simüle etmek için NumPy’nin shuffle işleviyle havuzdaki değerleri rastgele sıralayıp dilim indisleriyle özgün gruplarla aynı büyüklükte iki grup seçebiliriz.

def simulate_groups(data):
    group1, group2 = data
    n, m = len(group1), len(group2)

    pool = np.hstack(data)
    np.random.shuffle(pool)
    return pool[:n], pool[-m:]

Bu işlev her çağrıldığında abs_diff_means işlevine verebileceğimiz bir dizi demeti döndürür.

abs_diff_means(simulate_groups(data))
np.float64(0.031193045602279312)

Aşağıdaki döngü deneyi çok kez simüle eder ve her simüle edilmiş veri kümesinde ortalamalar arasındaki farkı hesaplar.

simulated_diffs = [abs_diff_means(simulate_groups(data)) for i in range(1001)]

Sonuçları görselleştirmek için simüle edilmiş sonuçlardan oluşan örneklemi alıp dağılımına yaklaşan bir Pmf oluşturan aşağıdaki işlevi kullanacağız.

from scipy.stats import gaussian_kde
from empiricaldist import Pmf


def make_pmf(sample, low, high):
    kde = gaussian_kde(sample)
    qs = np.linspace(low, high, 201)
    ps = kde(qs)
    return Pmf(ps, qs)

Dağılımın kuyruğunu dolduran bu işlevi de kullanacağız.

from thinkstats import underride


def fill_tail(pmf, observed, side, **options):
    """PMF altında gözlenen değerin sağında ya da solunda kalan alanı doldurur."""
    options = underride(options, alpha=0.3)

    if side == "right":
        condition = pmf.qs >= observed
    elif side == "left":
        condition = pmf.qs <= observed

    series = pmf[condition]
    plt.fill_between(series.index, 0, series, **options)

Simüle edilmiş sonuçların dağılımı şöyledir. Gölgeli bölge, sıfır hipotezi altındaki ortalama farkının gözlenen farkı aştığı durumları gösterir. Bu bölgenin alanı p-değeridir.

pmf = make_pmf(simulated_diffs, 0, 0.2)
pmf.plot()
fill_tail(pmf, observed_diff, "right")
decorate(xlabel="Ortalamalar arasındaki mutlak fark (hafta)", ylabel="Yoğunluk")
_images/d332a5d2a6fcc72ebe64778cbf618ad5af00bf79b8279deeea4e69331290092c.png

Aşağıdaki işlev, gözlenen değer kadar büyük ya da ondan büyük simüle edilmiş değerlerin oranı olan p-değerini hesaplar.

def compute_p_value(simulated, observed):
    """Gözlenen değer kadar büyük ya da daha büyük simüle edilmiş değerlerin oranı."""
    return (np.asarray(simulated) >= observed).mean()

Bu örnekte p-değeri yaklaşık %18’dir; yani 0,078 hafta kadar büyük bir farkın şans eseri ortaya çıkması makuldür.

compute_p_value(simulated_diffs, observed_diff)
np.float64(0.1838161838161838)

Bu sonuca dayanarak ilk bebeklerin gebelik sürelerinin genel olarak daha uzun olduğundan emin olamayız; bu veri kümesindeki fark şanstan kaynaklanmış olabilir.

İki hipotez testi örneğinde de aynı öğeleri gördük: test istatistiği, sıfır hipotezi ve sıfır hipotezinin modeli. Burada test istatistiği ortalamalar arasındaki mutlak farktır. Sıfır hipotezi gebelik süresi dağılımının iki grupta gerçekte aynı olduğudur. Sıfır hipotezini iki grubun verilerini tek havuzda birleştirip karıştırarak ve özgünlerle aynı büyüklükte iki gruba ayırarak modelledik. Bu sürece, karıştırmanın başka bir adı olan permütasyon denir.

Hipotez testine bu hesaplamalı yaklaşım, farklı istatistikleri sınamak için öğeleri kolayca birleştirmeyi sağlar.

9.3. Diğer test istatistikleri#

İlk bebekler ile diğerlerinin gebelik sürelerinin değişkenliği arasında fark olup olmadığını merak edebiliriz. Bu hipotezi test etmek için iki grubun standart sapmaları arasındaki mutlak farkı test istatistiği olarak kullanabiliriz. Aşağıdaki işlev bunu hesaplar.

def abs_diff_stds(data):
    group1, group2 = data
    diff = np.std(group1) - np.std(group2)
    return np.abs(diff)

NSFG veri kümesinde standart sapmalar arasındaki fark yaklaşık 0,18’dir.

observed_diff = abs_diff_stds(data)
observed_diff
np.float64(0.17600895913991677)

Bu farkın şanstan kaynaklanıp kaynaklanamayacağını görmek için yine permütasyon kullanabiliriz. Aşağıdaki döngü sıfır hipotezini çok kez simüle eder ve her veri kümesindeki standart sapma farkını hesaplar.

simulated_diffs = [abs_diff_stds(simulate_groups(data)) for i in range(1001)]

Sonuçların dağılımı şöyledir. Gölgeli bölge yine sıfır hipotezi altındaki test istatistiğinin gözlenen farkı aştığı yeri gösterir.

pmf = make_pmf(simulated_diffs, 0, 0.5)
pmf.plot()
fill_tail(pmf, observed_diff, "right")
decorate(xlabel="Standart sapmalar arasındaki mutlak fark (hafta)", ylabel="Yoğunluk")
_images/0dd96dfee593a2596e43ffeb3a9d5b2287a178d20358e5f9e3104f870f7e9891.png

Gözlenen fark kadar büyük ya da daha büyük sonuçların oranını hesaplayarak bu bölgenin alanını tahmin edebiliriz.

compute_p_value(simulated_diffs, observed_diff)
np.float64(0.17082917082917082)

p-değeri yaklaşık 0,17’dir; dolayısıyla iki grup aynı olsa bile bu kadar büyük bir fark görmemiz makuldür. Sonuç olarak ilk bebeklerin gebelik sürelerinin genel olarak daha değişken olduğundan emin olamayız; veri kümesindeki fark şanstan kaynaklanmış olabilir.

9.4. Korelasyon testi#

Korelasyonları sınamak için aynı çerçeveyi kullanabiliriz. Örneğin NSFG veri kümesinde doğum ağırlığı ile annenin yaşı arasında korelasyon vardır; daha yaşlı annelerin bebekleri ortalama olarak daha ağırdır. Peki bu etki şanstan kaynaklanabilir mi?

Bunu öğrenmek için verileri hazırlayacağız. Canlı doğumlardan annenin yaşının ve doğum ağırlığının bilindiği durumları seçeceğiz.

valid = live.dropna(subset=["agepreg", "totalwgt_lb"])
valid.shape
(9038, 244)

Ardından ilgili sütunları seçeceğiz.

ages = valid["agepreg"]
birthweights = valid["totalwgt_lb"]

Aşağıdaki işlev bir xs ve ys demeti alıp pozitif ya da negatif korelasyonun büyüklüğünü hesaplar.

def abs_correlation(data):
    xs, ys = data
    corr = np.corrcoef(xs, ys)[0, 1]
    return np.abs(corr)

NSFG veri kümesinde korelasyon yaklaşık 0,07’dir.

data = ages, birthweights
observed_corr = abs_correlation(data)
observed_corr
np.float64(0.06883397035410906)

Sıfır hipotezi, annenin yaşı ile doğum ağırlığı arasında korelasyon olmadığıdır. Gözlenen değerleri karıştırarak yaş ve doğum ağırlığı dağılımlarının aynı, ancak değişkenlerin ilişkisiz olduğu bir dünyayı simüle edebiliriz.

Aşağıdaki işlev bir xs ve ys demeti alır, xs değerlerini karıştırır ve karıştırılmış xs ile özgün ys değerlerini içeren bir demet döndürür. Bunun yerine ys değerlerini ya da ikisini birden karıştırsak da çalışırdı.

def permute(data):
    xs, ys = data
    new_xs = xs.values.copy()
    np.random.shuffle(new_xs)
    return new_xs, ys

Karıştırılmış değerlerin korelasyonu genellikle 0’a yakındır.

abs_correlation(permute(data))
np.float64(0.0019269515502894341)

Aşağıdaki döngü çok sayıda karıştırılmış veri kümesi üretip her birinin korelasyonunu hesaplar.

simulated_corrs = [abs_correlation(permute(data)) for i in range(1001)]

Sonuçların dağılımı şöyle görünür. Dikey noktalı çizgi gözlenen korelasyonu gösterir.

pmf = make_pmf(simulated_corrs, 0, 0.07)
pmf.plot()
plt.axvline(observed_corr, color="gray", ls=":")
decorate(xlabel="Korelasyonun mutlak değeri", ylabel="Yoğunluk")
_images/fd6bd2feefb763964a9b6663972e6fc7addff69cdf167d088d298937a16ab346.png

Gözlenen korelasyonun dağılım kuyruğunda olduğunu ve eğri altında görünür bir alan kalmadığını görebiliriz. p-değerini hesaplamaya çalışırsak sonuç 0’dır; bu, simülasyonların hiçbirinde karıştırılmış verinin korelasyonunun gözlenen değeri aşmadığını gösterir.

compute_p_value(simulated_corrs, observed_corr)
np.float64(0.0)

Bu hesaba dayanarak p-değerinin muhtemelen 1/1000’den küçük olduğu, ancak gerçekte sıfır olmadığı sonucuna varabiliriz. Karıştırılmış verinin korelasyonunun gözlenen değeri aşması düşük olasılıklıdır, fakat olanaksız değildir.

p-değeri küçük olduğunda —geleneksel olarak 0,05’ten küçükse— sonucun istatistiksel olarak anlamlı olduğunu söyleyebiliriz. Ancak p-değerlerini böyle yorumlamak her zaman sorunlu olmuştur ve giderek daha az kullanılmaktadır.

Sorunlardan biri geleneksel eşiğin keyfî ve her uygulama için uygun olmamasıdır. Bir diğeri, “anlamlı” sözcüğünün etkinin uygulamada önemli olduğunu düşündürerek yanıltmasıdır. Annenin yaşı ile doğum ağırlığı arasındaki korelasyon iyi bir örnektir: istatistiksel olarak anlamlı, ancak önem taşımayacak kadar küçüktür.

Başka bir seçenek p-değerlerini nitel olarak yorumlamaktır.

  • p-değeri büyükse gözlenen etkinin şans eseri ortaya çıkması makuldür.

  • p-değeri küçükse etkinin şanstan kaynaklanma olasılığını çoğu zaman eleyebiliriz; ancak temsil edici olmayan örnekleme ya da ölçüm hatalarından kaynaklanabileceğini unutmamalıyız.

9.5. Oran testi#

Son örnek olarak test istatistiği seçiminin biraz düşünmeyi gerektirdiği bir durumu ele alalım. Bir kumarhane işlettiğinizi ve bir müşterinin hileli, yani yüzlerden birini diğerlerinden daha olası kılacak biçimde değiştirilmiş zar kullandığından kuşkulandığınızı varsayın. Şüpheliyi yakalayıp zara el koydunuz; şimdi hileli olduğunu kanıtlamanız gerekiyor. Zarı 60 kez atıp 1 ile 6 arasındaki her sonucun sıklığını kaydediyorsunuz. Sonuçlar aşağıdaki Hist nesnesindedir.

from empiricaldist import Hist

qs = np.arange(1, 7)
freqs = [8, 9, 19, 5, 8, 11]
observed = Hist(freqs, qs)
observed.index.name = "outcome"
observed
freqs
outcome
1 8
2 9
3 19
4 5
5 8
6 11

Her değerin ortalama 10 kez görünmesini beklersiniz. Bu veri kümesinde 3 beklenenden daha sık, 4 daha seyrek görünür. Peki bu farklar şans eseri oluşabilir mi?

Hipotezi test etmek için her sonucun beklenen sıklığını hesaplayarak başlayacağız.

num_rolls = observed.sum()
outcomes = observed.qs
expected = Hist(num_rolls / 6, outcomes)

Aşağıdaki işlev gözlenen ve beklenen sıklıkları alıp mutlak farkların toplamını hesaplar.

def total_abs_deviation(observed):
    return np.sum(np.abs(observed - expected))

Gözlenen veri kümesinde bu test istatistiği 20’dir.

observed_dev = total_abs_deviation(observed)
observed_dev
np.float64(20.0)

Aşağıdaki işlev gözlenen veriyi alır, adil bir zarı aynı sayıda atmayı simüle eder ve simüle edilmiş sıklıkları içeren bir Hist nesnesi döndürür.

def simulate_dice(observed):
    num_rolls = np.sum(observed)
    rolls = np.random.choice(observed.qs, num_rolls, replace=True)
    hist = Hist.from_seq(rolls)
    return hist

Aşağıdaki döngü deneyi çok kez simüle edip her seferinde toplam mutlak sapmayı hesaplar.

simulated_devs = [total_abs_deviation(simulate_dice(observed)) for i in range(1001)]

Test istatistiğinin sıfır hipotezi altındaki dağılımı şöyledir. Toplamın her zaman çift olduğuna dikkat edin; bir sonuç beklenenden sık göründüğünde başka bir sonuç daha seyrek görünmek zorundadır.

pmf_devs = Pmf.from_seq(simulated_devs)
pmf_devs.bar()

decorate(xlabel="Toplam mutlak sapma", ylabel="PMF")
_images/111de05de4d8b63599ec87a8c735bb4b56bfbad2cf6e6d4f481605baf2faaba5.png

Toplam 20 sapmanın olağandışı olmadığını görebiliriz. p-değeri yaklaşık %13’tür; bu nedenle zarın hileli olduğundan emin olamayız.

compute_p_value(simulated_devs, observed_dev)
np.float64(0.13086913086913088)

Ancak seçtiğimiz test istatistiği tek seçenek değildi. Bu tür bir problemde aşağıdaki gibi hesaplayabileceğimiz ki-kare istatistiğini kullanmak daha gelenekseldir.

def chi_squared_stat(observed):
    diffs = (observed - expected) ** 2
    return np.sum(diffs / expected)

Sapmaların mutlak değerlerini almak yerine karelerini almak büyük sapmalara daha fazla ağırlık verir. expected değerine bölmek sapmaları standartlaştırır; ancak burada beklenen sıklıkların tümü eşit olduğundan sonucu etkilemez.

observed_chi2 = chi_squared_stat(observed)
observed_chi2
np.float64(11.6)

Gözlenen verinin ki-kare istatistiği 11,6’dır. Bu sayı tek başına pek anlamlı değildir; ancak simüle edilmiş zar atışlarının sonuçlarıyla karşılaştırabiliriz. Aşağıdaki döngü çok sayıda simüle edilmiş veri kümesi üretip her birinin ki-kare istatistiğini hesaplar.

simulated_chi2 = [chi_squared_stat(simulate_dice(observed)) for i in range(1001)]

Bu test istatistiğinin sıfır hipotezi altındaki dağılımı şöyledir. Gölgeli bölge gözlenen değeri aşan sonuçları gösterir.

pmf = make_pmf(simulated_chi2, 0, 20)
pmf.plot()
fill_tail(pmf, observed_chi2, "right")
decorate(xlabel="Ki-kare istatistiği", ylabel="Yoğunluk")
_images/879f48b7554f0a443c8e28a64e2a0209d3061ac6280a281e5afe6f68f2e08b33.png

Gölgeli bölgenin alanı yine p-değeridir.

compute_p_value(simulated_chi2, observed_chi2)
np.float64(0.04495504495504495)

Ki-kare istatistiğiyle p-değeri yaklaşık 0,04’tür; toplam sapmayla elde ettiğimiz 0,13’ten belirgin biçimde küçüktür. %5 eşiğini ciddiye alırsak bu etkiyi istatistiksel olarak anlamlı sayardık. Ancak iki testi birlikte düşününce sonuçların kesin olmadığı görüşündeyim. Zarın hileli olma olasılığını elemezdim, fakat sanığı da suçlu bulmazdım.

Bu örnek önemli bir noktayı gösterir: p-değeri test istatistiği ile sıfır hipotezi modelinin seçimine bağlıdır ve bazen bir etkinin istatistiksel olarak anlamlı sayılıp sayılmayacağını bu seçimler belirler.

9.6. Sözlük#

  • hipotez testi (hypothesis testing): Gözlenen bir etkinin rastgele örneklemeden kaynaklanmasının makul olup olmadığını denetleme yöntemleri.

  • test istatistiği (test statistic): Hipotez testinde gözlenen etkinin büyüklüğünü nicelleştiren istatistik.

  • sıfır hipotezi (null hypothesis): Örneklemde gözlenen etkinin evrende bulunmadığı varsayımına dayanan sistem modeli.

  • permütasyon (permutation): Veri kümesini rastgele karıştırarak sıfır hipotezini simüle etme yolu.

  • p-değeri (p-value): Sıfır hipotezi altında gözlenen etki kadar büyük bir etkinin olasılığı.

  • istatistiksel olarak anlamlı (statistically significant): p-değeri seçilmiş, çoğu zaman %5 olan eşikten küçük etki. Büyük veri kümelerinde uygulamada önem taşımayacak kadar küçük bir etki bile istatistiksel olarak anlamlı olabilir.

9.7. Alıştırmalar#

9.7.1. Alıştırma 9.1#

Bölüm 8’deki penguen verileriyle hipotez testi yapalım. Verileri indirme yönergeleri bu bölümün notebook’unda yer alıyor.

Aşağıdaki hücre verileri Allison Horst tarafından oluşturulan bir depodan indirir.

Horst AM, Hill AP, Gorman KB (2020). palmerpenguins: Palmer Archipelago (Antarctica) penguin data. R paketi, sürüm 0.1.0. https://allisonhorst.github.io/palmerpenguins/. doi: 10.5281/zenodo.3960218.

Veriler şu makaleye temel olan araştırma kapsamında toplanmıştır: Gorman KB, Williams TD, Fraser WR (2014). Ecological sexual dimorphism and environmental variability within a community of Antarctic penguins (genus Pygoscelis). PLoS ONE 9(3):e90081. https://doi.org/10.1371/journal.pone.0090081

download(
    "https://raw.githubusercontent.com/allisonhorst/palmerpenguins/c19a904462482430170bfe2c718775ddb7dbb885/inst/extdata/penguins_raw.csv"
)

Verileri şöyle okuyup sakallı penguenleri seçebiliriz.

penguins = pd.read_csv("penguins_raw.csv").dropna(subset=["Body Mass (g)"])
chinstrap = penguins.query('Species.str.startswith("Chinstrap")')
chinstrap.shape
(68, 17)

Erkek ve dişi penguenlerin kilogram cinsinden ağırlıklarını şöyle çıkarabiliriz.

male = chinstrap.query("Sex == 'MALE'")
weights_male = male["Body Mass (g)"] / 1000
weights_male.mean()
np.float64(3.9389705882352937)
female = chinstrap.query("Sex == 'FEMALE'")
weights_female = female["Body Mass (g)"] / 1000
weights_female.mean()
np.float64(3.5272058823529413)

İki grubun ağırlık dağılımının aynı olduğu sıfır hipotezi altında çok sayıda simüle edilmiş veri kümesi üretmek ve her birinde ortalama farkını hesaplamak için abs_diff_means ile simulate_groups kullanın. Simülasyon sonuçlarını gözlenen farkla karşılaştırıp p-değerini hesaplayın. Gruplar arasındaki gözlenen farkın şanstan kaynaklanması makul mü?

9.7.2. Alıştırma 9.2#

Önceki alıştırmadaki penguen verilerinden dişi penguenlerin gaga sırtı derinliklerini ve uzunluklarını çıkarabiliriz (gaga sırtı, gaganın üst kenarıdır).

data = female["Culmen Depth (mm)"], female["Culmen Length (mm)"]

Bu değişkenler arasındaki korelasyon yaklaşık 0,26’dır.

observed_corr = abs_correlation(data)
observed_corr
np.float64(0.2563170802728449)

Ölçümler arasında gerçekte korelasyon bulunmasa bile bu korelasyonun şans eseri ortaya çıkıp çıkamayacağına bakalım. Verilerin çok sayıda permütasyonunu üretmek için permute, her birinin korelasyonunu hesaplamak için abs_correlation kullanın. Sıfır hipotezi altındaki korelasyon dağılımını çizip gözlenen korelasyonun p-değerini hesaplayın. Sonucu nasıl yorumlarsınız?

Think Stats: Python ile Keşifsel Veri Analizi, 3. Baskı

Telif hakkı 2024 Allen B. Downey

Kod lisansı: MIT Lisansı

Metin lisansı: Creative Commons Atıf-Gayriticari-AynıLisanslaPaylaş 4.0 Uluslararası