Code
#install.packages("coin")
#install.packages("perm")
#install.packages("RVAideMemoire")Testy permutacyjne to podejście nieparametryczne, które dzięki rozwojowi metod komputerowych stało się szeroko stosowane we współczesnej statystyce. Metody te znajdują szczególne zastosowanie w dziedzinach takich jak biostatystyka, psychologia oraz badania kliniczne, gdzie badacze często dysponują niewielkimi próbami danych, które nie spełniają rygorystycznych założeń o normalności rozkładu.
Główna idea opiera się na założeniu, że jeśli między badanymi grupami nie ma żadnej realnej różnicy, to etykiety przypisane do poszczególnych wyników nie mają znaczenia. W praktyce najpierw obliczamy wynik rzeczywisty, na przykład różnicę średnich między naszymi grupami. Następnie program komputerowy “miesza” wszystkie wyniki i losowo przydziela je do grup od nowa, tworząc sztuczne zestawy danych. Proces ten jest powtarzany tysiące razy, a za każdym razem komputer zapisuje wynik, jaki wyszedł w danym losowym rozdaniu. Na koniec porównujemy nasz pierwotny, prawdziwy wynik z całym zbiorem wyników uzyskanych przez losowanie. Jeśli nasz wynik jest bardzo rzadki na tle tych wygenerowanych przypadkowo, uznajemy go za istotny statystycznie.
#install.packages("coin")
#install.packages("perm")
#install.packages("RVAideMemoire")Załóżmy, że porównujemy dwie grupy: \(A\) i \(B\) o licznościach \(n_A\) i \(n_B\). Chcemy sprawdzić, czy średnie w tych grupach różnią się istotnie.
\[ p = \frac{\sum_{i=1}^{B} I(|D^*_i| \ge |D_{obs}|)}{B} \]
set.seed(123)
#Generowanie danych
grupa_A <- rnorm(20, mean = 10, sd = 2)
grupa_B <- rnorm(20, mean = 11.5, sd = 2)
obserwowana_roznica <- mean(grupa_B) - mean(grupa_A)
#Łączenie danych
wszystkie_dane <- c(grupa_A, grupa_B)
N <- length(wszystkie_dane)
n_A <- length(grupa_A)
#Symulacja permutacji
B <- 10000
wyniki_perm <- numeric(B)
for(i in 1:B) {
indeksy <- sample(1:N, n_A, replace = FALSE)
perm_A <- wszystkie_dane[indeksy]
perm_B <- wszystkie_dane[-indeksy]
wyniki_perm[i] <- mean(perm_B) - mean(perm_A)
}
#p-value
p_val <- sum(abs(wyniki_perm) >= abs(obserwowana_roznica)) / B
#Histogram
hist(wyniki_perm, breaks = 50, col = "lightblue", border = "white", main = "Histogram rozkładu permutacyjnego różnicy średnich", xlab = "Różnica średnich")
abline(v = obserwowana_roznica, col = "red", lwd = 2, lty = 2)
text(obserwowana_roznica, 500, paste("Wynik obserwowany\n",
"p-value = ", p_val), pos = 4, col = "red")cat("P-value: ", p_val)P-value: 0.0618
W przeciwieństwie do prostych pętli, pakiet ten wykorzystuje statystyki liniowe i macierze wpływów, co pozwala na wyznaczanie rozkładu statystyki testowej zarówno metodami dokładnymi dla małych prób, jak i metodą Monte Carlo dla większych zbiorów danych.
library(coin)
set.seed(456)
# Generowanie danych
dane <- data.frame(
wynik = c(rnorm(15, 50, 10),
rnorm(15, 58, 10)),
grupa = factor(rep(c("A", "B"), each = 15))
)
# Test permutacyjny
test_res <- oneway_test(
wynik ~ grupa,
data = dane,
distribution = approximate(nresample = 10000)
)
# Wartości statystyki testowej
rozklad_stat <- support(test_res)
# Statystyka obserwowana
statystyka_obs <- statistic(test_res)
# p-value
p_val <- pvalue(test_res)
# Histogram
hist(
rozklad_stat,
breaks = 40,
col = "lightgreen",
border = "white",
probability = TRUE,
main = "Wartości statystyki testowej",
xlab = "Statystyka testowa"
)
# Linia wyniku obserwowanego
abline(
v = statystyka_obs,
col = "darkblue",
lwd = 2,
lty = 2
)
# Opis
text(
statystyka_obs,
0.05,
labels = paste0(
"Wynik obserwowany\n",
"p-value = ",
round(p_val, 4)
),
pos = 4,
col = "darkblue"
)# Wynik testu
print(test_res)
Approximative Two-Sample Fisher-Pitman Permutation Test
data: wynik by grupa (A, B)
Z = -2.2267, p-value = 0.025
alternative hypothesis: true mu is not equal to 0
Pakiet perm jest często stosowany w analizie problemu Behrensa-Fishera, szczególnie gdy klasyczne założenie o równości wariancji jest naruszone.
if (!require("perm")) install.packages("perm")
library(perm)
set.seed(123)
# Generowanie danych (Problem Behrensa-Fishera)
n1 <- 15
n2 <- 15
dane_bf <- data.frame(
wynik = c(rnorm(n1, 50, 5), rnorm(n2, 58, 15)),
grupa = factor(rep(c("A", "B"), each = 15))
)
# Wykonanie testu metodą Monte Carlo
test_bf <- permTS(wynik ~ grupa, data = dane_bf,
method = "exact.mc",
control = permControl(nmc = 10000))
B <- 10000
rozk_fp <- replicate(B, {
p_labels <- sample(dane_bf$grupa)
mean(dane_bf$wynik[p_labels == "B"]) - mean(dane_bf$wynik[p_labels == "A"])
})
obs_diff <- mean(dane_bf$wynik[dane_bf$grupa == "B"]) -
mean(dane_bf$wynik[dane_bf$grupa == "A"])
# Histogram
hist(rozk_fp, breaks = 45, col = "lightblue", border = "white",
main = "Rozkład referencyjny Fishera-Pitmana",
xlab = "Różnica średnich", probability = TRUE)
# Dodanie wyniku zaobserwowanego
abline(v = obs_diff, col = "red", lwd = 2, lty = 2)
text(obs_diff, 0.01, "Różnica zaobserwowana", pos = 4, col = "red")cat("P-value dla problemu Behrensa-Fishera:", test_bf$p.value)P-value dla problemu Behrensa-Fishera: 0.4249575
Pakiet ten oferuje funkcję perm.t.test(), która stanowi permutacyjną wersję klasycznego testu t-Studenta. Jest to szczególnie przydatne narzędzie w kontekście problemu Behrensa-Fishera, gdy chcemy uniknąć metod opartych na losowaniu ze zwracaniem (Bootstrap).
if (!require("RVAideMemoire")) install.packages("RVAideMemoire")
library(RVAideMemoire)
set.seed(123)
#Dane
n1 <- 15
n2 <- 15
dane_rv <- data.frame(
wynik = c(rnorm(n1, 50, 5), rnorm(n2, 55, 12)),
grupa = factor(rep(c("A", "B"), each = 15))
)
#Wykonanie testu
invisible(capture.output(
res_rv <- perm.t.test(wynik ~ grupa, data = dane_rv, nperm = 9999)
))
#Statystyka obserwowana
obs_t <- t.test(wynik ~ grupa, data = dane_rv)$statistic
#Rozkład do wizualizacji
rozk_t <- replicate(9999, {
temp_data <- dane_rv
temp_data$grupa <- sample(temp_data$grupa)
t.test(wynik ~ grupa, data = temp_data)$statistic
})
#Wykres
hist(rozk_t, breaks = 45, col = "thistle", border = "white",
main = "Rozkład referencyjny statystyki t",
xlab = "Wartość statystyki t*", probability = TRUE)
#Wynik obserwowany
abline(v = obs_t, col = "darkmagenta", lwd = 2, lty = 2)
text(
obs_t,
0.38,
labels = "Statystyka obserwowana",
pos = 4,
col = "darkmagenta"
)cat("P-value z testu RVAideMemoire:", res_rv$p.value)P-value z testu RVAideMemoire: 0.7196
Pitman, E. J. G. (1938). Significance tests which may be applied to samples from any populations. III. The analysis of variance test. Biometrika, 29(3/4), 322–335.
Test permutacyjny. (n.d.). W Wikipedia.
Link
Behrens–Fisher problem. (n.d.). In Wikipedia.
Link