Python ile Hipotez Testi

Enes Eren
6 min readApr 3, 2023

Hipotez testi, bir hipotezin doğruluğunun istatistiksel bir güvenilirlik aralığında saptanması için kullanılan yöntemdir. Hipotez testi, Wikipedia

Hipotez ise, bilimsel yöntemde olaylar arasında ilişkiler kurmak ve olayları bir nedene bağlamak üzere tasarlanan ve geçerli sayılan bir önermedir. Hipotez, Wikipedia

Daha fazlası için bu konuda yazmış olduğum yazıya bakabilirsiniz: İstatistiğe Giriş: Korelasyon ve Hipotez Testleri

Şimdi ise hipotez testini Python kullanarak uygulayacağız.

Elimizde late_shipments adında bir veri seti bulunmaktadır. Bu veri seti medikal ürünlerin teslimatı ile ilgili bilgiler içermektedir. late değişkeninde Yes ve No değerleri bulunmaktadır. Bu değerler teslimatın gecikmesi ile ilgili bir cevaptır.

Paketleri ve Veri Setini İçe Aktaralım

import pandas as pd
import numpy as np
import pingouin
from statsmodels.stats.proportion import proportions_ztest
scipy.stats import chisquare

late_shipments = pd.read_csv('late_shipments.csv')

A/B Testi

A/B testi temelde bir kullanıcı deneyimi araştırma metodolojisidir. A/B testlerinde bir internet sitesi, mobil uygulama ya da bir dijital servis arayüzünün iki farklı sürümü karşılaştırılarak hangisinin daha iyi performans gösterdiği belirlenmeye çalışılır.

late değişkeninin değerlerinin oranlarına bakalım.

late_prop_samp = late_shipments['late'].value_counts(normalize=True)

print(late_prop_samp)
    No     0.939
Yes 0.061
Name: late, dtype: float64

Teslimatların %6.1'i geç kalmış.

Örneğin gecikmelerin %6 olduğu ile ilgili bir hipotez önerelim.

late_prop_hyp = 0.06

Standart hatayı bulalım.

std_error = np.std(late_shipments_boot_distn, ddof=1)

late_shipments_boot_distn, geç teslimatların oranını içeren bir yeniden örnekleme dağılımıdır. Bunun standart sapmasını alıyoruz.

Z değerini bulalım.

z_score = (late_prop_samp - late_prop_hyp) / std_error

print(z_score)
0.13353771933071554

Z değeri örneklem istatistiği ve hipotez istatistiği arasındaki farkı ölçen bir değerdir. Yani burada hipotez istatistiğimiz örneklem istatistiğinden %13,35 sapmıştır.

P Değeri

p değeri, bir istatistiksel modele bağlı olarak gözlemlenen örneklem sonuçlarının (bir test istatistiği) ne kadar aşırı olduğunu ölçmek için kullanılan bir fonksiyondur. P değeri, Wikipedia

Yani daha büyük p değeri sıfır hipotezini destekler.

z_score = (late_prop_samp - late_prop_hyp) / std_error

p_value = 1 - norm.cdf(z_score)

print(p_value)
0.4468840678346485

P değerini, z değerini kümülatif normal dağılım fonksiyonu ile dönüştürerek elde edebiliriz.

Güven Aralığı

Bir anakütle parametre değerinin tek bir sayı ile kestirimi yapılacağına, bu parametre değerini kapsayabilecek iki (alt ve üst sınır) sayıdan oluşan bir aralık bulunur. Böylece güven aralıkları bir kestirimin ne kadar güvenilir olduğunu gösterir.

lower = np.quantile(late_shipments_boot_distn, 0.025)
upper = np.quantile(late_shipments_boot_distn, 0.975)

print((lower, upper))
(0.047, 0.076)

0.06 sıfır hipotezimiz %95 güven aralığında olduğundan ve yüksek p değeri sebebiyle sıfır hipotezini reddedemeyiz.

T Testleri

İki ortalama arasındaki farkın istatistiksel anlamlılığını test etmek için kullanılan parametrik bir tekniktir.

Örneğin, bazı tesilmatların neden geciktiğini belirlemeye çalışırken zamanında gelen gönderilerin ağırlığının geciken teslimatların ağırlığından az olup olmadığını öğrenmek isteyelim.

Teslimatların gecikme durumuna göre ağırlıklarının ortalamasını bulalım ve bunların farkını alalım.

numerator = xbar_no - xbar_yes

xbar_no ve xbar_yes değişkenleri geciken ve gecikmeyen teslimatların ortalama ağırlıklarını içerir. T testi istatistiğinin paydasını hesaplayalım.

denominator = np.sqrt(s_no ** 2 / n_no + s_yes ** 2 / n_yes)

s_no ve s_yes geciken ve gecikmeyen teslimatların standart sapmasını içerir. Karelerini alıp böldükten sonra karekökünü alıyoruz.

t_stat = numerator / denominator

# Print the test statistic
print(t_stat)
-2.3936661778766433

Buradaki değer, hesapladığımız sıraya göre -2,39 veya 2,39 civarındadır.

Şuana kadar t istatistiğini manuel olarak hesapladık. Ancak pingouin paketi bize bunları hızlıca yapabilmemizi sağlayan bazı fonksiyonları içermektedir.

test_results = pingouin.ttest(x=sample_dem_data['diff'], 
y=0,
alternative="two-sided")

print(test_results)
                 T  dof alternative       p-val         CI95%  cohen-d        BF10  power
T-test 30.298 499 two-sided 3.601e-115 [6.39, 7.27] 1.355 2.246e+111 1.0

ANOVA Testleri (ANalysis Of VAriance)

Gruplar arasındaki farklılıklar için kullanılan bir testtir.

Örneğin teslimatların teslimat yöntemine göre fiyatların ortalamasına bakalım.

xbar_pack_by_mode = late_shipments.groupby("shipment_mode")['pack_price'].mean()

print(xbar_pack_by_mode)
    shipment_mode
Air 39.712
Air Charter 4.227
Ocean 6.432
Name: pack_price, dtype: float64

Her bir teslimat yöntemi için fiyatın standart sapmasını hesaplayalım.

s_pack_by_mode = late_shipments.groupby("shipment_mode")['pack_price'].std()

print(s_pack_by_mode)
    Air            48.933
Air Charter 0.993
Ocean 5.303
Name: pack_price, dtype: float64

Görünüşe göre her teslimat yönteminin fiyatları birbirinden oldukça farklı. ANOVA testi uygulayalım.

anova_results = pingouin.anova(data=late_shipments,
dv="pack_price",
between="shipment_mode")

print(anova_results)
              Source  ddof1  ddof2       F      p-unc    np2
0 shipment_mode 2 997 21.865 5.089e-10 0.042

P değeri anlamlılık düzeyinden düşük ya da eşit olduğunda sıfır hipotezi reddedilir. Teslimat yöntemleri arasında paket fiyatlarında önemli bir fark vardır. Ancak, bunun hangi teslimat yöntemleri için geçerli olduğunu bilmiyoruz.

Tek Oran Testi

İki grup arasındaki oran farkını test etmek için kullanılır. İlk yaptığımız hipotez testinde bilmediğimiz bir popülasyonun oranının belirli bir değere sahip olduğunu ya da olmadığını ölçmüştük. Yeniden örneklemeyi örneklem üzerinde kullanarak standart hatayı tahmin ettik. Daha sonra standart hatayı z değerini hesaplamak için kullandık, onu da p değerini elde etmek için. En sonunda hipotezimizin reddedilip edilmediğine karar verebildik. Oranlar için test istatistiğini hesaplamada parametrenin tek bir tahmini olduğundan z istatistiğini kullanırız. T istatistiği yalnızca iki bilinmeyen değeri tahmin etmede kullanılabilecek bir testtir.

Tek oran için test uygulayalım.

Örneğin geç teslimatların %6 olduğunu hipotez olarak önerelim.

p_0 = 0.06

Geç teslimatların örneklem oranını hesaplayalım.

p_hat = (late_shipments['late'] == "Yes").mean()

Örneklem büyüklüğünü alalım.

n = len(late_shipments)

print(p_hat, n)
    0.061 1000

Test istatistiğinin payını ve paydasını hesaplayalım.

numerator = p_hat - p_0
denominator = np.sqrt(p_0 * (1 - p_0) / n)

Test istatistiğini hesaplayalım.

z_score = numerator / denominator

print(z_score)
    0.13315591032282698

Z değerini kullanarak p değerini bulalım.

p_value = 1 - norm.cdf(z_score)

print(p_value)
    0.44703503936503364

Tek oran testinden sıfır hipotezimiz için elde ettiğimiz p değeri büyük (0.44 > 0.05) olduğundan sıfır hipotezi reddedilmez.

İki Oran Testi

Navlun için ödenen tutarın, teslimatın gecikip gecikmediğini etkileyip etkilemediğini düşünebiliriz.

Elimizde ns adında navlun ücretine göre oluşturulmuş bir grup bulunmaktadır.

print(ns)
freight_cost_group
expensive 545
reasonable 455
Name: late, dtype: int64

Bunu kullanarak popülasyon oranının tahminini hesaplayalım.

p_hat = (p_hats["reasonable"] * ns["reasonable"] +
p_hats["expensive"] * ns["expensive"]) / (ns["reasonable"] +
ns["expensive"])

Bu değerin 1'den farkını alalım.

p_hat_times_not_p_hat = p_hat * (1 - p_hat)

Standart hatayı hesaplayalım.

p_hat_times_not_p_hat_over_ns = p_hat_times_not_p_hat / ns["expensive"] +
p_hat_times_not_p_hat / ns["reasonable"]
std_error = np.sqrt(p_hat_times_not_p_hat_over_ns)

print(std_error)
    late
Yes 0.015
Name: late, dtype: float64

Z değerini hesaplayalım.

z_score = (p_hats["expensive"] - p_hats["reasonable"]) / std_error

print(z_score)
    late
Yes 3.119
Name: late, dtype: float64

P değerini hesaplayalım.

p_value = 1 - norm.cdf(z_score)

# Print p_value
print(p_value)
   [0.00090721]

0.00090 < 0.05 olduğundan bu bize yüksek navlun ücretine sahip teslimatların büyük oranda geç kaldığını göstermektedir.

statsmodels paketinden proportions_ztest fonksiyonunu kullanarak aynı sonucu da elde edebiliriz.

# Her bir navlun grubunun geç teslimat sayısını bulalım
late_by_freight_cost_group = late_shipments.groupby("freight_cost_group")['late'].value_counts()

success_counts = np.array([45, 16])

n = np.array([45 + 500, 16 + 439])

# İki oran arasında z testi uygulayalım.
stat, p_value = proportions_ztest(count=success_counts, nobs=n,
alternative="larger")

print(stat, p_value)
    3.1190401865206128 0.0009072060637051224

Ki-kare Testi

Çeşitli grupların oranlarının birbirine eşit olup olmadığının testidir.

Ki-kare hipotez testleri, ki-kare dağılımına dayanır. T-dağılımı gibi, serbestlik dereceleri ve merkezi olmama parametreleri vardır.

Ki-kare test istatistiği bir kare sayıdır, bu nedenle her zaman negatif değildir, bu nedenle yalnızca sağ kuyruklu olma eğilimindedir.

Ki-kare bağımsızlık testi, bir kategorik değişkenin başarı oranlarını başka bir kategorik değişkenin kategorileri boyunca karşılaştırır.

late_shipments veri seti, belirli bir teslimata uygulanan incoterms’i açıklayan bir vendor_inco_term içerir:

  • EXW: “Fabrika teslimi”. Alıcı, malların nakliyesini öder.
  • CIP: “Nakliye ve sigorta ödenmiş”. Mallar gemiye binene kadar navlun ve sigorta masraflarını satıcı öder.
  • DDP: “Gümrük vergisi ödenmiş olarak teslim edildi”. Satıcı, varış limanına ulaşana kadar malların nakliye ücretini öder.
  • FCA: “Ücretsiz taşıyıcı”. Satıcı, malların taşınması için ödeme yapar.

Belki de incoterms, navlun maliyetlerinin pahalı olup olmadığını etkiler. Bu hipotezleri 0.01 anlamlılık düzeyinde test edelim.

Navlun gruplarını incoterms’e göre gruplandıralım.

props = late_shipments.groupby('vendor_inco_term')['freight_cost_group'].value_counts(normalize=True)

wide_props = props.unstack()

print(wide_props)
    freight_cost_group  expensive  reasonable
vendor_inco_term
CIP 0.393 0.607
DDP 0.550 0.450
EXW 0.587 0.413
FCA 0.342 0.658

Grupların bağımsız olup olmadığını belirleyelim.

expected, observed, stats = pingouin.chi2_independence(data=late_shipments, x="vendor_inco_term", y="freight_cost_group")

print(stats[stats['test'] == 'pearson'])
          test  lambda    chi2  dof       pval  cramer  power
0 pearson 1.0 28.941 3.0 2.304e-06 0.17 0.998

P değerine bakarak sıfır hipotezi reddedilir. Yani incoterms ile navlun grupları arasında bir ilişki bulunmaktadır.

Kategorik bir değişkendeki başarı oranlarını başka bir kategorik değişkenin grupları arasında karşılaştırma testi, ki-kare bağımsızlık testi olarak adlandırılır.

Ki-kare uyum testi, bir değişkenin belirli bir dağılımdan gelme olasılığının olup olmadığını belirlemek için kullanılan bir istatistiksel hipotez testidir.

Bunu scipy.stats modülündeki chisquare fonksiyonunu kullanarak bunu yapabiliriz.

gof_test = chisquare(f_obs=incoterm_counts['n'], 
f_exp=hypothesized['n'])

print(gof_test)
Power_divergenceResult(statistic=2.3633633633633613, pvalue=0.5004909543758

Uyum testimiz sıfır hipotezimizi reddetmez.

Hipotez Testi Varsayımları

  • Bütün hipotez testleri her bir örneklemin popülasyondan rassal olarak elde edildiğini varsayar. Aksi takdirde örneklemler rassal değil ise popülasyonu yansıtma şansı yoktur, yani yanlılık içerir. Bunun için verinin nasıl toplandığını anlamamız gerekir. Eğer anlayamazsak, veriyi toplayan ilgili kişi veya kurum ile iletişime geçilmelidir. Bu zahmete katlanılmalıdır yoksa yapılacak testler anlamsızdır.
  • Bazı durumlar hariç testler bütün gözlemlerin bağımsız olduğunu varsayar. Eğer gözlemler bağımsız değil ise test sonuçları yanıltıcı olabilir.
  • Eğer örneklem yeteri kadar büyük ise merkezi limit teoremi geçerlidir.
  • Bir t testi uygulamak için her bir örneklemde en az 30 gözlem bulunmalıdır. Bu sayı oran testlerinde 10, ki-kare testlerinde ise 5'tir.

Örneklem Büyüklüğü Testi

Bir hipotez testi yapmak ve sonucun makul olduğundan emin olmak için, bir örneğin üç gereksinimi karşılaması gerekir: popülasyonun rastgele bir örneğidir, gözlemler bağımsızdır ve yeterli gözlem vardır. Bunlardan yalnızca son koşul kolayca test edilebilir.

T-testleri için;

counts = late_shipments['freight_cost_group'].value_counts()

print(counts)

print((counts >= 30).all())
expensive     545
reasonable 454
Name: freight_cost_group, dtype: int64
True

Oran testleri için;

counts = late_shipments['late'].value_counts()

print(counts)

print((counts >= 10).all())
No     938
Yes 61
Name: late, dtype: int64
True

Ki-kare testleri için;

counts = late_shipments.groupby('vendor_inco_term')['freight_cost_group'].value_counts()

print(counts)

print((counts >= 5).all())
    vendor_inco_term  freight_cost_group
CIP reasonable 34
expensive 22
DDP expensive 55
reasonable 45
EXW expensive 430
reasonable 302
FCA reasonable 73
expensive 38
Name: freight_cost_group, dtype: int64
True

Son

Beni Linkedin ve Github üzerinden takip edebilirsiniz.

--

--