Въведение: Защо статистическият анализ е толкова важен за дейта специалистите
Можете да съберете данните, да ги почистите перфектно и да направите красиви графики — но без статистически анализ всъщност не знаете дали откритията ви са реални или просто случайност. И честно казано, точно това разделя „разглеждане на данни" от „анализ на данни".
Точно тук влизат в действие статистическите тестове. Те ви дават обективен начин да потвърдите или отхвърлите наблюденията си с числа, а не с интуиция.
В Python екосистемата две библиотеки доминират тази област: SciPy (версия 1.17.1 към март 2026 г.) за провеждане на статистически тестове и Statsmodels (версия 0.14.6) за регресионен анализ и статистическо моделиране. Заедно с Pandas и NumPy те формират завършен инструментариум, с който можете да анализирате данни от всякакъв мащаб.
Хайде да минем стъпка по стъпка през целия процес — от описателна статистика до тестване на хипотези и регресионен анализ. Всеки раздел включва работещ код, който можете директно да копирате и адаптирате.
Инсталация и настройка на средата
Необходими библиотеки
За да следвате примерите, ще ви трябват следните пакети:
pip install scipy==1.17.1 statsmodels==0.14.6 pandas numpy matplotlib seaborn
Импортиране на модулите
Ето стандартният набор от импорти, който ще ползваме през цялото ръководство:
import numpy as np
import pandas as pd
from scipy import stats
import statsmodels.api as sm
import statsmodels.formula.api as smf
import matplotlib.pyplot as plt
import seaborn as sns
# Настройка за по-добри графики
plt.style.use('seaborn-v0_8-whitegrid')
sns.set_context('notebook', font_scale=1.1)
Описателна статистика: Първата стъпка на всеки анализ
Преди да стигнете до тестове и модели, винаги започвайте с описателна статистика. Сериозно — пропускането на тази стъпка е една от най-честите грешки, които виждам. Описателната статистика ви дава усещане за данните: какви са средните стойности, как са разпределени, има ли крайни стойности, които биха объркали анализа.
Основни мерки с Pandas
# Зареждане на примерни данни
np.random.seed(42)
df = pd.DataFrame({
'възраст': np.random.normal(35, 10, 200).astype(int),
'заплата': np.random.normal(3500, 800, 200).round(2),
'опит_години': np.random.exponential(5, 200).round(1),
'отдел': np.random.choice(['IT', 'Маркетинг', 'Финанси', 'HR'], 200)
})
# Пълен статистически обзор
print(df.describe())
# Допълнителни мерки
print(f"Медиана на заплатата: {df['заплата'].median():.2f}")
print(f"Стандартно отклонение: {df['заплата'].std():.2f}")
print(f"Асиметрия (skewness): {df['заплата'].skew():.4f}")
print(f"Ексцес (kurtosis): {df['заплата'].kurtosis():.4f}")
Групирана статистика
Когато искате да сравнявате групи, groupby() е вашият най-добър приятел:
# Статистика по отдели
отдел_статистика = df.groupby('отдел')['заплата'].agg([
'count', 'mean', 'median', 'std', 'min', 'max'
]).round(2)
print(отдел_статистика)
Тестване на хипотези: Основни концепции
Тестването на хипотези е структуриран подход за вземане на решения на базата на данни. Вместо да казвате „изглежда, че група А се представя по-добре от група Б", формулирате го като математически тест с ясен, количествен отговор.
Ключови термини
- Нулева хипотеза (H₀) — твърдението, че няма разлика или ефект. Например: „Средната заплата в IT и Маркетинг отделите е еднаква."
- Алтернативна хипотеза (H₁) — твърдението, че разлика или ефект съществува.
- p-стойност (p-value) — вероятността да наблюдавате толкова екстремен резултат, ако нулевата хипотеза е вярна. По-ниска p-стойност = по-силни доказателства срещу H₀.
- Ниво на значимост (α) — предварително зададен праг, обикновено 0.05. Ако p-стойността е под α, отхвърляме H₀.
- Тестова статистика — числова мярка (t, F, χ² и др.), която показва колко далеч са данните от очакванията при H₀.
Как да изберете правилния тест
Изборът на статистически тест зависи от три основни фактора:
- Тип на данните — числови (непрекъснати) или категорийни
- Брой групи — две или повече
- Зависимост между извадките — независими или свързани (paired)
Ето кратка справочна таблица (запазете си я някъде — ще ви трябва):
| Ситуация | Тест | SciPy функция |
|---------------------------------------|-------------------------|-------------------------|
| Средна на извадка vs. стойност | Едноизвадков t-тест | stats.ttest_1samp() |
| Средни на 2 независими групи | Двуизвадков t-тест | stats.ttest_ind() |
| Средни на 2 свързани групи | Сдвоен t-тест | stats.ttest_rel() |
| Средни на 3+ групи | Еднофакторен ANOVA | stats.f_oneway() |
| Връзка между 2 категорийни променливи | Хи-квадрат тест | stats.chi2_contingency()|
| Проверка за нормалност | Shapiro-Wilk тест | stats.shapiro() |
| 2 групи, ненормални данни | Mann-Whitney U тест | stats.mannwhitneyu() |
T-тестове: Сравняване на средни стойности
Едноизвадков t-тест
Използвайте го, когато искате да проверите дали средната стойност на извадка се различава от определена стойност. Класически пример — дали средната заплата в компанията отговаря на заявената.
# Дали средната заплата в компанията се различава от 3500 лв.?
t_stat, p_value = stats.ttest_1samp(df['заплата'], 3500)
print(f"t-статистика: {t_stat:.4f}")
print(f"p-стойност: {p_value:.4f}")
alpha = 0.05
if p_value < alpha:
print("Отхвърляме H₀: Средната заплата е статистически различна от 3500 лв.")
else:
print("Не отхвърляме H₀: Няма достатъчно доказателства за разлика.")
Двуизвадков t-тест (независими извадки)
Това е може би най-често използваният тест в практиката — сравнява средните стойности на две независими групи. Един съвет от личен опит: винаги първо проверявайте равенството на дисперсиите с Levene's тест. Ако ги пропуснете, рискувате да получите подвеждащи резултати.
# Дали заплатите в IT и Маркетинг отделите се различават?
заплати_it = df[df['отдел'] == 'IT']['заплата']
заплати_маркетинг = df[df['отдел'] == 'Маркетинг']['заплата']
# Първо проверяваме равенството на дисперсиите с Levene's тест
levene_stat, levene_p = stats.levene(заплати_it, заплати_маркетинг)
print(f"Levene's тест p-стойност: {levene_p:.4f}")
# Избираме подходящия тест
equal_var = levene_p > 0.05
t_stat, p_value = stats.ttest_ind(заплати_it, заплати_маркетинг, equal_var=equal_var)
тест_тип = "Student's t-тест" if equal_var else "Welch's t-тест"
print(f"\n{тест_тип}:")
print(f"t-статистика: {t_stat:.4f}")
print(f"p-стойност: {p_value:.4f}")
# Доверителен интервал за разликата
ci = stats.ttest_ind(заплати_it, заплати_маркетинг, equal_var=equal_var)
print(f"\nСредна IT: {заплати_it.mean():.2f}, Средна Маркетинг: {заплати_маркетинг.mean():.2f}")
print(f"Разлика: {заплати_it.mean() - заплати_маркетинг.mean():.2f}")
Сдвоен t-тест (зависими извадки)
Когато измервате едни и същи субекти преди и след дадена интервенция — например ефекта от обучение върху представянето на служители:
# Симулираме резултати преди и след обучение
np.random.seed(123)
преди = np.random.normal(65, 12, 30)
след = преди + np.random.normal(8, 5, 30) # Средно подобрение от ~8 точки
t_stat, p_value = stats.ttest_rel(преди, след)
print(f"Средно преди: {преди.mean():.2f}")
print(f"Средно след: {след.mean():.2f}")
print(f"Средна разлика: {(след - преди).mean():.2f}")
print(f"t-статистика: {t_stat:.4f}")
print(f"p-стойност: {p_value:.4f}")
if p_value < 0.05:
print("Обучението води до статистически значимо подобрение.")
Хи-квадрат тест: Анализ на категорийни данни
Хи-квадрат тестът за независимост проверява дали съществува връзка между две категорийни променливи. Това е изключително полезен тест, който често бива подценяван — особено при анализ на анкетни данни или A/B тестове с категорийни резултати.
# Има ли връзка между отдел и ниво на удовлетвореност?
np.random.seed(42)
n = 300
данни = pd.DataFrame({
'отдел': np.random.choice(['IT', 'Маркетинг', 'Финанси'], n),
'удовлетвореност': np.random.choice(['Ниска', 'Средна', 'Висока'], n,
p=[0.2, 0.5, 0.3])
})
# Създаване на кръстосана таблица (contingency table)
contingency = pd.crosstab(данни['отдел'], данни['удовлетвореност'])
print("Кръстосана таблица:")
print(contingency)
# Провеждане на Хи-квадрат теста
chi2, p_value, dof, expected = stats.chi2_contingency(contingency)
print(f"\nХи-квадрат статистика: {chi2:.4f}")
print(f"Степени на свобода: {dof}")
print(f"p-стойност: {p_value:.4f}")
print(f"\nОчаквани честоти (ако няма връзка):")
print(pd.DataFrame(expected,
index=contingency.index,
columns=contingency.columns).round(2))
ANOVA: Сравняване на три и повече групи
Когато имате повече от две групи и искате да знаете дали поне една от тях се различава значимо от останалите, t-тестът вече не свърши работа (правенето на множество t-тестове води до проблема с множествените сравнения). Тук на помощ идва ANOVA.
# Различават ли се заплатите между четирите отдела?
групи = [група['заплата'].values for _, група in df.groupby('отдел')]
f_stat, p_value = stats.f_oneway(*групи)
print(f"F-статистика: {f_stat:.4f}")
print(f"p-стойност: {p_value:.4f}")
if p_value < 0.05:
print("Има статистически значима разлика между поне два отдела.")
else:
print("Няма значима разлика между отделите.")
Post-hoc анализ с Tukey HSD
Добре, ANOVA каза, че има разлика — но кои точно групи се различават? За тази цел ползваме post-hoc тест на Tukey:
from statsmodels.stats.multicomp import pairwise_tukeyhsd
tukey = pairwise_tukeyhsd(df['заплата'], df['отдел'], alpha=0.05)
print(tukey.summary())
# Визуализация на резултатите
fig = tukey.plot_simultaneous(figsize=(10, 5))
plt.title('Tukey HSD: Сравнение на заплатите по отдели')
plt.xlabel('Средна заплата (лв.)')
plt.tight_layout()
plt.show()
Проверка за нормалност на разпределението
Повечето параметрични тестове (t-тест, ANOVA) предполагат нормално разпределение на данните. И тук идва уловката — мнозина пропускат тази проверка и директно прилагат тестовете. Не правете тази грешка.
Shapiro-Wilk тест
# Shapiro-Wilk тест — препоръчва се за извадки до 5000 елемента
stat, p_value = stats.shapiro(df['заплата'])
print(f"Shapiro-Wilk статистика: {stat:.4f}")
print(f"p-стойност: {p_value:.4f}")
if p_value > 0.05:
print("Данните не се отклоняват значимо от нормалното разпределение.")
else:
print("Данните се отклоняват значимо от нормалното разпределение.")
D'Agostino-Pearson тест
# Подходящ за по-големи извадки (n > 20)
stat, p_value = stats.normaltest(df['заплата'])
print(f"D'Agostino-Pearson статистика: {stat:.4f}")
print(f"p-стойност: {p_value:.4f}")
Визуална проверка с Q-Q Plot
Числата са важни, но понякога е полезно просто да погледнете данните визуално. Q-Q plot-ът сравнява вашите данни с теоретичното нормално разпределение — ако точките следват диагоналната линия, данните са приблизително нормални.
from scipy.stats import probplot
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# Хистограма с крива на нормалното разпределение
axes[0].hist(df['заплата'], bins=25, density=True, alpha=0.7, color='steelblue')
x = np.linspace(df['заплата'].min(), df['заплата'].max(), 100)
axes[0].plot(x, stats.norm.pdf(x, df['заплата'].mean(), df['заплата'].std()),
'r-', lw=2, label='Нормално разпределение')
axes[0].set_title('Хистограма на заплатите')
axes[0].set_xlabel('Заплата (лв.)')
axes[0].legend()
# Q-Q Plot
probplot(df['заплата'], dist="norm", plot=axes[1])
axes[1].set_title('Q-Q Plot')
plt.tight_layout()
plt.show()
Непараметрични тестове: Когато данните не са нормални
Ако проверката за нормалност показа, че данните ви не следват нормално разпределение — без паника. Има непараметрични алтернативи за почти всеки параметричен тест:
# Mann-Whitney U тест (алтернатива на двуизвадковия t-тест)
u_stat, p_value = stats.mannwhitneyu(заплати_it, заплати_маркетинг, alternative='two-sided')
print(f"Mann-Whitney U статистика: {u_stat:.4f}")
print(f"p-стойност: {p_value:.4f}")
# Wilcoxon тест за сдвоени извадки (алтернатива на сдвоения t-тест)
w_stat, p_value = stats.wilcoxon(преди, след)
print(f"\nWilcoxon статистика: {w_stat:.4f}")
print(f"p-стойност: {p_value:.4f}")
# Kruskal-Wallis тест (алтернатива на ANOVA)
h_stat, p_value = stats.kruskal(*групи)
print(f"\nKruskal-Wallis H статистика: {h_stat:.4f}")
print(f"p-стойност: {p_value:.4f}")
Корелационен анализ
Корелацията измерва силата и посоката на връзката между две числови променливи. Важно е да запомните: корелацията показва асоциация, не каузалност. Но повече за това по-долу.
Pearson корелация
# Корелация между опит и заплата
r, p_value = stats.pearsonr(df['опит_години'], df['заплата'])
print(f"Pearson r: {r:.4f}")
print(f"p-стойност: {p_value:.4f}")
if abs(r) > 0.7:
сила = "силна"
elif abs(r) > 0.4:
сила = "умерена"
elif abs(r) > 0.2:
сила = "слаба"
else:
сила = "много слаба"
посока = "положителна" if r > 0 else "отрицателна"
print(f"Интерпретация: {сила} {посока} корелация")
Spearman корелация
Когато връзката не е линейна или работите с рангови данни, Spearman е по-подходящият избор:
# Spearman ранг корелация
rho, p_value = stats.spearmanr(df['опит_години'], df['заплата'])
print(f"Spearman ρ: {rho:.4f}")
print(f"p-стойност: {p_value:.4f}")
Корелационна матрица с визуализация
# Корелационна матрица
числови_колони = df.select_dtypes(include=[np.number])
corr_matrix = числови_колони.corr()
# Визуализация с Heatmap
plt.figure(figsize=(8, 6))
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0,
fmt='.3f', square=True, linewidths=0.5)
plt.title('Корелационна матрица')
plt.tight_layout()
plt.show()
Регресионен анализ със Statsmodels
Регресията ви позволява да моделирате връзката между зависима и една (или повече) независими променливи — и най-важното, да правите прогнози. Тук Statsmodels наистина блести, защото дава изключително подробен изход, подобен на R.
Проста линейна регресия
# Модел: заплата ~ опит_години
X = sm.add_constant(df['опит_години']) # Добавяне на константа (intercept)
model = sm.OLS(df['заплата'], X).fit()
print(model.summary())
# Извличане на ключови метрики
print(f"\nR² (коефициент на детерминация): {model.rsquared:.4f}")
print(f"Adj. R²: {model.rsquared_adj:.4f}")
print(f"F-статистика: {model.fvalue:.4f}")
print(f"p-стойност на модела: {model.f_pvalue:.6f}")
Множествена линейна регресия
Ако сте свикнали с R синтаксиса за формули, ще оцените формулния интерфейс на Statsmodels:
# Използване на формулен интерфейс (подобно на R)
model_multi = smf.ols('заплата ~ опит_години + възраст + C(отдел)', data=df).fit()
print(model_multi.summary())
Визуализация на регресията
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# Scatter plot с регресионна линия
axes[0].scatter(df['опит_години'], df['заплата'], alpha=0.5, color='steelblue')
x_line = np.linspace(df['опит_години'].min(), df['опит_години'].max(), 100)
X_line = sm.add_constant(x_line)
y_pred = model.predict(X_line)
axes[0].plot(x_line, y_pred, 'r-', lw=2, label=f'R² = {model.rsquared:.3f}')
axes[0].set_xlabel('Опит (години)')
axes[0].set_ylabel('Заплата (лв.)')
axes[0].set_title('Линейна регресия: Заплата ~ Опит')
axes[0].legend()
# Residuals plot
residuals = model.resid
axes[1].scatter(model.fittedvalues, residuals, alpha=0.5, color='steelblue')
axes[1].axhline(y=0, color='r', linestyle='--')
axes[1].set_xlabel('Предвидени стойности')
axes[1].set_ylabel('Остатъци (residuals)')
axes[1].set_title('Анализ на остатъците')
plt.tight_layout()
plt.show()
Диагностика на регресионния модел
Изграждането на модел е само половината от работата — и то по-лесната половина. Трябва да проверите дали допусканията на регресията са изпълнени, иначе резултатите ви може да са ненадеждни.
# 1. Проверка за нормалност на остатъците
stat, p_norm = stats.shapiro(model.resid)
print(f"Shapiro-Wilk на остатъците: p = {p_norm:.4f}")
# 2. Проверка за хомоскедастичност (Breusch-Pagan тест)
from statsmodels.stats.diagnostic import het_breuschpagan
bp_stat, bp_p, _, _ = het_breuschpagan(model.resid, model.model.exog)
print(f"Breusch-Pagan тест: p = {bp_p:.4f}")
# 3. Проверка за автокорелация (Durbin-Watson)
from statsmodels.stats.stattools import durbin_watson
dw = durbin_watson(model.resid)
print(f"Durbin-Watson статистика: {dw:.4f}")
print(f"(Стойности около 2.0 означават липса на автокорелация)")
# 4. Проверка за мултиколинеарност (VIF)
from statsmodels.stats.outliers_influence import variance_inflation_factor
X_multi = df[['опит_години', 'възраст']]
X_multi = sm.add_constant(X_multi)
for i, col in enumerate(X_multi.columns):
vif = variance_inflation_factor(X_multi.values, i)
print(f"VIF за {col}: {vif:.2f}")
Практически пример: Пълен статистически анализ от край до край
Нека съберем всичко в един цялостен пример. Ще анализираме данни за ефективността на три различни маркетингови кампании — нещо, което доста често се среща на практика.
np.random.seed(2026)
# Генериране на реалистични данни за маркетингови кампании
кампания_а = np.random.normal(150, 30, 80) # Email кампания
кампания_б = np.random.normal(165, 35, 75) # Social media кампания
кампания_в = np.random.normal(145, 28, 85) # PPC кампания
campaigns_df = pd.DataFrame({
'приходи': np.concatenate([кампания_а, кампания_б, кампания_в]),
'кампания': (['Email'] * 80 + ['Social Media'] * 75 + ['PPC'] * 85)
})
# Стъпка 1: Описателна статистика
print("=== Описателна статистика ===")
print(campaigns_df.groupby('кампания')['приходи'].describe().round(2))
# Стъпка 2: Визуализация
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
sns.boxplot(data=campaigns_df, x='кампания', y='приходи', ax=axes[0], palette='Set2')
axes[0].set_title('Разпределение на приходите по кампании')
axes[0].set_ylabel('Приходи (лв.)')
sns.histplot(data=campaigns_df, x='приходи', hue='кампания',
kde=True, ax=axes[1], palette='Set2', alpha=0.5)
axes[1].set_title('Хистограма на приходите')
plt.tight_layout()
plt.show()
# Стъпка 3: Проверка за нормалност (за всяка група)
print("\n=== Проверка за нормалност (Shapiro-Wilk) ===")
for кампания in ['Email', 'Social Media', 'PPC']:
данни = campaigns_df[campaigns_df['кампания'] == кампания]['приходи']
stat, p = stats.shapiro(данни)
статус = '(нормално)' if p > 0.05 else '(не е нормално)'
print(f"{кампания}: W = {stat:.4f}, p = {p:.4f} {статус}")
# Стъпка 4: Проверка за равенство на дисперсиите (Levene)
print("\n=== Levene's тест за хомоскедастичност ===")
групи_данни = [campaigns_df[campaigns_df['кампания'] == к]['приходи']
for к in ['Email', 'Social Media', 'PPC']]
lev_stat, lev_p = stats.levene(*групи_данни)
print(f"Levene статистика: {lev_stat:.4f}, p = {lev_p:.4f}")
# Стъпка 5: ANOVA
print("\n=== Еднофакторен ANOVA ===")
f_stat, anova_p = stats.f_oneway(*групи_данни)
print(f"F-статистика: {f_stat:.4f}")
print(f"p-стойност: {anova_p:.4f}")
# Стъпка 6: Post-hoc анализ (ако ANOVA е значим)
if anova_p < 0.05:
print("\n=== Tukey HSD Post-hoc тест ===")
tukey = pairwise_tukeyhsd(campaigns_df['приходи'],
campaigns_df['кампания'], alpha=0.05)
print(tukey.summary())
# Стъпка 7: Изводи
print("\n=== Заключение ===")
if anova_p < 0.05:
print(f"ANOVA показва значима разлика между кампаниите (F={f_stat:.2f}, p={anova_p:.4f}).")
print("Проверете Tukey HSD резултатите за конкретните двойки.")
else:
print(f"ANOVA не показва значима разлика (F={f_stat:.2f}, p={anova_p:.4f}).")
print("Няма достатъчно доказателства, че кампаниите се различават.")
Размер на ефекта: Отвъд p-стойността
Ето нещо, което много начинаещи пропускат: статистическата значимост не означава автоматично практическа значимост. Може да имате p-стойност от 0.001, но реалната разлика да е толкова малка, че няма значение на практика. Затова винаги изчислявайте размера на ефекта.
# Cohen's d за две групи
def cohens_d(group1, group2):
n1, n2 = len(group1), len(group2)
var1, var2 = group1.var(), group2.var()
pooled_std = np.sqrt(((n1 - 1) * var1 + (n2 - 1) * var2) / (n1 + n2 - 2))
return (group1.mean() - group2.mean()) / pooled_std
d = cohens_d(кампания_б, кампания_а)
print(f"Cohen's d (Social Media vs Email): {d:.4f}")
if abs(d) < 0.2:
print("Интерпретация: Пренебрежимо малък ефект")
elif abs(d) < 0.5:
print("Интерпретация: Малък ефект")
elif abs(d) < 0.8:
print("Интерпретация: Среден ефект")
else:
print("Интерпретация: Голям ефект")
# Eta-squared за ANOVA
ss_between = sum(len(g) * (g.mean() - campaigns_df['приходи'].mean())**2
for g in групи_данни)
ss_total = sum((campaigns_df['приходи'] - campaigns_df['приходи'].mean())**2)
eta_sq = ss_between / ss_total
print(f"\nEta² (ANOVA ефект): {eta_sq:.4f}")
print(f"Кампанията обяснява {eta_sq*100:.1f}% от вариацията в приходите.")
Често срещани грешки и как да ги избегнете
След доста проекти с реални данни мога да кажа, че тези грешки се повтарят отново и отново:
- p-hacking — Не тествайте множество хипотези, докато намерите значим резултат. Ако правите множество сравнения, приложете корекция на Bonferroni или FDR. Това е наистина важно и е причина за доста неуспешни репликации в науката.
- Объркване на корелация с каузалност — Корелацията между две променливи не означава, че едната причинява другата. Може да има скрит конфаундър, който влияе на двете.
- Игнориране на допусканията — Винаги проверявайте дали данните отговарят на предпоставките на теста: нормалност, хомоскедастичност, независимост. Отнема 2-3 реда код и спестява много главоболия.
- Малки извадки — При много малки извадки (n < 20) дори значителни разлики може да не достигнат статистическа значимост. Обмислете анализ на мощността преди да събирате данни.
- Еднопосочно тълкуване на p-стойността — p-стойност от 0.06 не означава, че няма ефект. Просто казва, че доказателствата не са достатъчно силни при зададеното ниво. Контекстът има значение.
Често задавани въпроси (FAQ)
Каква е разликата между SciPy и Statsmodels за статистически анализ?
SciPy (scipy.stats) предоставя бързи функции за отделни статистически тестове — t-тестове, хи-квадрат, ANOVA и други. Statsmodels е по-подходящ за изграждане на статистически модели (регресия, времеви редове), предлагайки подробен изход с коефициенти, доверителни интервали и диагностики. На практика двете се допълват чудесно: SciPy за бърз тест, Statsmodels за пълен модел.
Кога да използвам параметричен и кога непараметричен тест?
Параметричните тестове (t-тест, ANOVA) са по-мощни, но изискват данните да следват приблизително нормално разпределение и да имат равни дисперсии. Ако Shapiro-Wilk тестът отхвърли нулевата хипотеза или извадката ви е много малка, преминете към непараметрични алтернативи: Mann-Whitney U вместо t-тест, Kruskal-Wallis вместо ANOVA, Wilcoxon вместо сдвоен t-тест.
Какво означава p-стойност от 0.05 на практика?
Ако p-стойността е под 0.05, вероятността да наблюдавате този или по-екстремен резултат е под 5%, при условие че нулевата хипотеза е вярна. Но внимание — това не означава 95% вероятност вашата хипотеза да е вярна. Прагът 0.05 е конвенция и в различни области се използват различни нива (медицина: 0.01, социални науки: 0.10).
Как да избера между Pearson и Spearman корелация?
Pearson е правилният избор, когато връзката между променливите е линейна и данните са нормално разпределени. Spearman е за нелинейни монотонни връзки, рангови данни или когато имате крайни стойности (outliers), тъй като работи с ранговете, а не със суровите стойности.
Как да направя анализ на мощността (power analysis) в Python?
Използвайте модула statsmodels.stats.power. Ето бърз пример за изчисляване на нужния размер на извадката за t-тест:
from statsmodels.stats.power import TTestIndPower
analysis = TTestIndPower()
sample_size = analysis.solve_power(effect_size=0.5, alpha=0.05, power=0.8)
print(f"Необходим размер на извадката: {int(np.ceil(sample_size))} на група")