Статистически анализ и тестване на хипотези в Python със SciPy и Statsmodels

Научете как да провеждате t-тестове, ANOVA, хи-квадрат и регресия в Python със SciPy и Statsmodels — практическо ръководство с работещи примери и визуализации за 2026 г.

Въведение: Защо статистическият анализ е толкова важен за дейта специалистите

Можете да съберете данните, да ги почистите перфектно и да направите красиви графики — но без статистически анализ всъщност не знаете дали откритията ви са реални или просто случайност. И честно казано, точно това разделя „разглеждане на данни" от „анализ на данни".

Точно тук влизат в действие статистическите тестове. Те ви дават обективен начин да потвърдите или отхвърлите наблюденията си с числа, а не с интуиция.

В 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₀.

Как да изберете правилния тест

Изборът на статистически тест зависи от три основни фактора:

  1. Тип на данните — числови (непрекъснати) или категорийни
  2. Брой групи — две или повече
  3. Зависимост между извадките — независими или свързани (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))} на група")
За Автора Editorial Team

Our team of expert writers and editors.