Publikacje naukowe · Psychometria

DIF krok po kroku – Mantel–Haenszel, regresja logistyczna i IRT

Czy pozycja skali działa tak samo u kobiet i mężczyzn, młodszych i starszych albo w dwóch wersjach językowych? Pokazujemy trzy metody wykrywania DIF na jednych danych, ich mocne i słabe strony oraz to, co zrobić z pozycją, która „nie przeszła”.

Strona główna / Blog / DIF krok po kroku
W skrócie: DIF oznacza, że osoby z różnych grup o tym samym poziomie cechy różnią się prawdopodobieństwem odpowiedzi na pozycję. Mantel–Haenszel z klasyfikacją ETS dobrze wykrywa DIF jednorodny, ale nie widzi niejednorodnego; regresja logistyczna wykrywa oba typy, a IRT z kotwicą wskazuje, który parametr się różni. Oczyszczaj wynik dopasowujący, koryguj wielokrotne testy, podawaj miarę efektu i DTF, a o losie pozycji decyduj po analizie treści.

DIF: ta sama cecha, inna odpowiedź

O zróżnicowanym funkcjonowaniu pozycji (DIF) mówimy, gdy osoby z dwóch grup, które mają ten sam poziom mierzonej cechy, różnią się prawdopodobieństwem danej odpowiedzi. Sama różnica odsetków między grupami to jeszcze nie DIF. Jeśli starsi dorośli mają średnio więcej objawów depresyjnych, częściej odpowiadają „tak” na każdą pozycję. To prawdziwa różnica w cesze (ang. impact), a nie wada pomiaru. Dlatego każda metoda DIF porównuje grupy dopiero po dopasowaniu osób pod względem poziomu cechy.

Swaminathan i Rogers (1990) rozróżnili dwa rodzaje DIF:

  • DIF jednorodny (ang. uniform): jedna grupa ma przewagę na całym zakresie cechy. Krzywe charakterystyczne pozycji są równoległe i przesunięte. W IRT różni się próg (trudność) pozycji.
  • DIF niejednorodny (ang. non-uniform): różnica zależy od poziomu cechy, a krzywe mogą się przecinać. Różni się dyskryminacja, czyli w regresji logistycznej występuje interakcja grupy z poziomem cechy.

W modelu Rascha wszystkie pozycje mają tę samą dyskryminację, więc da się w nim opisać tylko DIF jednorodny. Teorię IRT przypomina wpis teoria reagowania na pozycje testowe. W poradniku IRT w R krok po kroku DIF jest jednym z kroków analizy modelu. Tutaj porównujemy trzy metody na tych samych danych: Mantela–Haenszela, regresję logistyczną i IRT.

Zmienna dopasowująca, kotwica i oczyszczanie

Każda metoda potrzebuje miary cechy, według której dopasowujesz osoby. W metodach obserwacyjnych jest to zwykle wynik sumaryczny skali, a w IRT – cecha ukryta θ, której skalę wyznaczają pozycje kotwiczące (ang. anchor items). Tu pojawia się błędne koło. Jeśli pozycja z DIF wchodzi do wyniku dopasowującego, zniekształca dopasowanie i może „przenosić” DIF na inne pozycje.

Rozwiązaniem jest oczyszczanie (ang. purification). Najpierw testujesz wszystkie pozycje. Potem liczysz wynik dopasowujący tylko z pozycji bez DIF i powtarzasz testy. Zwick (2012) w przeglądzie procedur ETS pokazuje, że oczyszczanie poprawia wykrywanie, gdy DIF ma głównie jeden kierunek, ale może je pogorszyć, gdy DIF w różnych pozycjach się równoważy. Gdy nie wiesz, jakiego wzorca się spodziewać, oczyszczanie jest zalecane. W pakiecie lordif oczyszczanie odbywa się iteracyjnie, aż do uzyskania stabilnego zestawu pozycji z DIF (Choi i in., 2011).

Przykład: lista objawów u młodszych i starszych dorosłych

Symulowaliśmy odpowiedzi tak/nie na 12 pozycji listy objawów depresyjnych. Grupą odniesienia są osoby młodsze (18–39 lat, n = 500), a grupą ogniskową starsze (60+, n = 500). Dane powstały z modelu dwuparametrycznego (2PL) i są dychotomiczne. Starsi mają w nich nieco wyższy średni poziom cechy, a dwie pozycje wbudowano z DIF:

  • p05 „budzę się dużo wcześniej niż zwykle” – DIF jednorodny: przy tym samym nasileniu depresji starsi częściej odpowiadają „tak”;
  • p09 „mam mniej energii niż zwykle” – DIF niejednorodny: u starszych pozycja słabiej różnicuje osoby (zmęczenie ma też inne przyczyny), więc krzywe się przecinają.

Wynik ogólny (0–12) wyniósł M = 4.90 (SD = 3.14) u młodszych i M = 5.85 (SD = 2.97) u starszych. Dane są symulowane (set.seed(2170)) i możesz je pobrać jako plik CSV (1000 wierszy: id, grupa, p01–p12).

Krok 1. Mantel–Haenszel i klasyfikacja ETS

Procedura Mantela–Haenszela (Mantel i Haenszel, 1959) dzieli próbę na warstwy według wyniku dopasowującego. W każdej warstwie tworzy tabelę 2 × 2 (grupa × odpowiedź), a następnie łączy je w test χ²MH i wspólny iloraz szans αMH. W bazowym R robi to funkcja mantelhaen.test() na tablicy grupa × odpowiedź × warstwa. Wartość αMH = 1 oznacza brak DIF. ETS przelicza ją na skalę delta:

ΔMH = −2.35 · ln(αMH)

Według reguł ETS opisanych przez Henninger i in. (2023) pozycja należy do kategorii A (DIF pomijalny), gdy |ΔMH| ≤ 1 albo ΔMH nie różni się istotnie od zera. Kategoria C (duży DIF) wymaga |ΔMH| ≥ 1.5 i wartości istotnie większej od 1. Pozostałe pozycje trafiają do kategorii B (umiarkowany DIF). Gdy obowiązuje model Rascha, a DIF jest jednorodny, ΔMH odpowiada różnicy trudności pozycji pomnożonej przez −2.35 (Henninger i in., 2023).

W pierwszym przebiegu tylko p05 miała wyraźny DIF: χ²MH = 40.37, αMH = 0.345, ΔMH = 2.50 (SE = 0.40), kategoria C, p po korekcie Holma < .001. Szanse odpowiedzi „tak” u młodszych stanowiły więc około jednej trzeciej szans starszych o tym samym wyniku. Po usunięciu p05 z wyniku dopasowującego p05 pozostała w kategorii C, a wszystkie inne pozycje w kategorii A.

Delta Mantela–Haenszela z 95% przedziałami ufności dla 12 pozycji po oczyszczeniu: p05 ma delta 2.50 i kategorię C, pozostałe pozycje, w tym p09 z delta −0.18, mieszczą się w kategorii A
Rysunek 1. ΔMH z 95% przedziałami ufności po oczyszczeniu wyniku dopasowującego. Szare pole to |Δ| ≤ 1 (kategoria A), czerwone pola to |Δ| ≥ 1.5. Pozycja p09 z DIF niejednorodnym wygląda „czysto”. Obliczenia: R (dane symulowane).

Rysunek pokazuje słabość metody. Pozycja p09 ma ΔMH = −0.18 (p = .649), choć jej krzywe w grupach wyraźnie się różnią. Wspólny iloraz szans uśrednia warstwy, więc przewaga starszych przy niskich wynikach i młodszych przy wysokich się znosi. Rogers i Swaminathan (1993) piszą wprost, że Mantel–Haenszel jest wrażliwy tylko na DIF jednego typu.

Krok 2. Regresja logistyczna: trzy modele zagnieżdżone

Swaminathan i Rogers (1990) zaproponowali, by dla każdej pozycji dopasować regresję logistyczną odpowiedzi na wynik dopasowujący S i grupę G:

M0: logit P = β0 + β1S M1: + β2G M2: + β3(S × G)

Porównanie M0 z M1 testuje DIF jednorodny, M1 z M2 – niejednorodny, a M0 z M2 daje łączny test o 2 stopniach swobody (Choi i in., 2011). Każde porównanie to test ilorazu wiarygodności różnicy dewiancji. W symulacjach procedura ta miała większą moc niż Mantel–Haenszel dla DIF niejednorodnego i podobną dla jednorodnego (Rogers i Swaminathan, 1993).

Przy dużych próbach istotne bywają nawet znikome różnice, dlatego do testu dodaje się miarę efektu: zmianę pseudo-R² między M0 a M2. Pierwsze proponowane progi (.13 i .26) późniejsze badania uznały za zbyt wysokie (Choi i in., 2011). Jodoin i Gierl (2001) zaproponowali niższe: ΔR² < .035 to efekt pomijalny, .035–.070 umiarkowany, a powyżej .070 duży. Pokazali też, że kryterium efektu wyraźnie zmniejsza liczbę fałszywych alarmów w dużych próbach, choć kosztem mocy. W przykładzie liczymy ΔR² Nagelkerkego.

Wyniki regresji logistycznej dla pozycji p05 i p09 po oczyszczeniu: łączny test, testy DIF jednorodnego i niejednorodnego, delta R kwadrat i klasyfikacja
Pozycjaχ²(2), M0 a M2p jednorodnyp niejednorodnyΔR²Klasa według Jodoin i Gierla
p0545.46, p < .001< .001.394.042umiarkowany
p0927.65, p < .001.933< .001.026pomijalny

Regresja poprawnie rozpoznała typ DIF obu pozycji. W p09 test jest jednoznaczny, a ΔR² mieści się w klasie „pomijalny”. Progi efektu to umowne kryteria, a nie werdykt. Przy DIF niejednorodnym zawsze obejrzyj krzywe w grupach (rysunek 2) i sprawdź, jak DIF wpływa na wynik całej skali.

Krok 3. IRT: model wielogrupowy z kotwicą

W IRT dopasowujesz model 2PL w obu grupach (mirt::multipleGroup) z wolną średnią i wariancją cechy w grupie ogniskowej. Następnie funkcją DIF() testujesz równość parametrów pozycji testem ilorazu wiarygodności (Chalmers, 2012). Kluczowy jest wybór kotwicy. Stark i in. (2006) zalecają testować dyskryminacje i progi razem, względem modelu bazowego, w którym ograniczona jest tylko kotwica, z poprawką Bonferroniego. Takie podejście okazało się skuteczniejsze niż wyjście od modelu, w którym wszystkie parametry są równe. Postępowaliśmy w trzech krokach:

  1. Przegląd (scheme = "drop"): każda pozycja testowana przy pozostałych jako kotwicy. Wskazał p05 (χ²(2) = 41.83) i p09 (χ²(2) = 29.58), obie z p po korekcie < .001.
  2. Kotwica: cztery pozycje najdalej od DIF w przeglądzie (p11, p08, p06, p02).
  3. Test właściwy (scheme = "add"): pozostałe osiem pozycji kolejno uwalniane przy stałej kotwicy. DIF potwierdził się tylko dla p05 (χ²(2) = 31.91) i p09 (χ²(2) = 25.85), z p po korekcie Holma < .001.

Osobne testy pokazały, który parametr się różni. W p05 był to wyraz wolny d, czyli próg (χ²(1) = 29.13, p < .001), a nie dyskryminacja (χ²(1) = 0.16, p = .690). W p09 było odwrotnie: dyskryminacja (χ²(1) = 25.50, p < .001), a nie próg (p = .173). W modelu końcowym próg p05 wyniósł −0.07 u młodszych i −0.84 u starszych, a dyskryminacja p09 odpowiednio 2.01 i 0.62. Średnia cechy u starszych wyniosła 0.28 (przy średniej 0 i wariancji 1 u młodszych), co jest różnicą w cesze, a nie DIF.

Krzywe charakterystyczne pozycji p05 i p09 u młodszych i starszych: w p05 krzywa starszych jest przesunięta w lewo (b −0.84 wobec −0.07), w p09 krzywa starszych jest płaska (a 0.62 wobec 2.01) i przecina krzywą młodszych w okolicy theta 0
Rysunek 2. Krzywe charakterystyczne pozycji z DIF w modelu końcowym. Linie to model 2PL, punkty to odsetki odpowiedzi „tak” w ośmiu przedziałach ocen θ (EAP). Po lewej DIF jednorodny, po prawej niejednorodny. Obliczenia: R (dane symulowane).

Porównanie trzech metod

Porównanie metod Mantela–Haenszela, regresji logistycznej i IRT na tych samych danych: wyniki dla pozycji p04, p05 i p09 oraz wymagania metod
Mantel–HaenszelRegresja logistycznaIRT (mirt)
p05 (DIF jednorodny)Δ = 2.50, kategoria Cp < .001, ΔR² = .042p < .001 (próg)
p09 (DIF niejednorodny)niewykryty, Δ = −0.18p < .001, ΔR² = .026p < .001 (dyskryminacja)
p04 (bez DIF)p = .021 bez korekty, .232 po korekcie (przebieg 1)p = 1.000 po korekciep = .439 po korekcie
Dopasowaniewynik sumarycznywynik sumaryczny (lub θ)θ z pozycji kotwiczących
Miara efektuΔMH, kategorie A/B/CΔR², współczynniki β2 i β3różnice parametrów, DTF
Kiedy wybraćszybki przegląd, mniejsze próby, DIF jednorodnystandard dla skal, oba typy DIFgdy i tak kalibrujesz pozycje w IRT

Metody zgodziły się co do p05, różniły w ocenie p09 i nie dały fałszywych alarmów po korekcie. Wniosek praktyczny: jeśli podajesz tylko Mantela–Haenszela, napisz, że metoda nie wykrywa DIF niejednorodnego, albo uzupełnij ją regresją logistyczną.

Wiele pozycji, wiele testów

Przy 12 pozycjach wykonujesz 12 testów, a przy oczyszczaniu i kilku metodach jeszcze więcej. Bez kontroli problemu wielokrotnych porównań fałszywe alarmy są niemal pewne. W przykładzie p04 bez DIF miała w MH p = .021, a w przeglądzie IRT p = .007. Po korekcie Holma oba wyniki przestały być istotne. Korektę (Holm, Benjamini–Hochberg albo Bonferroni) zapisz w planie analizy. Wybór omawia wpis poprawki na wielokrotne porównania. Zwick (2012) przypomina też drugą stronę: reguła kategorii C często słabo wykrywa DIF nawet w dużych próbach. Brak flagi nie dowodzi więc braku DIF.

DIF a inwariancja pomiaru w CFA

To samo pytanie zadaje inwariancja pomiaru w wielogrupowej CFA. Nierówne ładunki odpowiadają DIF niejednorodnemu (brak inwariancji metrycznej), a nierówne wyrazy wolne lub progi – jednorodnemu (brak inwariancji skalarnej). Stark i in. (2006) pokazali, że CFA i IRT wykrywają DIF podobnie dobrze, gdy stosujesz tę samą strategię kotwicy. Różnica leży głównie w perspektywie. Inwariancja zaczyna od całej skali i schodzi do pozycji, a DIF zaczyna od pozycji. Procedurę w lavaan opisuje inwariancja pomiaru krok po kroku, dla pozycji porządkowych przydaje się kategorialna CFA z WLSMV, a DIF względem zmiennej ciągłej, np. wieku w latach, zbadasz modelem MIMIC.

Co zrobić z pozycją z DIF

  1. Przeanalizuj treść. DIF to sygnał statystyczny, a nie dowód stronniczości. Zapytaj ekspertów i osoby z grupy ogniskowej, czy sformułowanie znaczy dla nich to samo. Przy przekładach to część adaptacji narzędzia (zob. adaptacja kulturowa kwestionariusza).
  2. Sprawdź skutek dla skali (DTF). Chalmers i in. (2016) zauważają, że łączny skutek DIF na poziomie testu bywa ważniejszy niż DIF pojedynczych pozycji. W przykładzie oczekiwany wynik starszych był średnio o 0.05 pkt wyższy niż młodszych o tym samym θ (sDTF = −0.05, 95% CI [−0.10, −0.02]), a bezwzględna różnica wyniosła 0.16 pkt, czyli 1.3% zakresu skali. Efekty obu pozycji częściowo się znoszą: przy θ = −1 starsi mają oczekiwany wynik 2.28 wobec 1.82, a przy θ = 2 – 10.33 wobec 10.54.
  3. Usuń pozycję, gdy DIF jest duży, treść tłumaczy go jako zniekształcenie, a skala bez niej zachowuje trafność i rzetelność.
  4. Rozdziel parametry w grupach (częściowa inwariancja), gdy porównujesz grupy na θ. Tak zbudowany jest model końcowy z przykładu.
  5. Zostaw i zgłoś, gdy DIF jest pomijalny, a DTF znikomy. Opisz wtedy, na podstawie jakich kryteriów podjęto decyzję.

Jak opisać analizę DIF w artykule

Podaj zmienną grupującą i liczebności grup, zmienną dopasowującą, sposób oczyszczania lub wyboru kotwicy, testy, korektę na wielokrotne testy, miary efektu i ich progi oraz decyzję o każdej pozycji z DIF. Wzór na podstawie przykładu:

Zróżnicowane funkcjonowanie pozycji (DIF) względem wieku (18–39 lat, n = 500; 60+, n = 500) oceniono trzema metodami. W procedurze Mantela–Haenszela wynik dopasowujący oczyszczono z pozycji z istotnym DIF, a pozycje sklasyfikowano według reguł ETS. W regresji logistycznej porównano trzy modele zagnieżdżone (Swaminathan i Rogers, 1990), a wielkość efektu oceniono zmianą R² Nagelkerkego według kryteriów Jodoin i Gierla (2001). W modelu 2PL w dwóch grupach (mirt; Chalmers, 2012) parametry testowano testem ilorazu wiarygodności względem kotwicy z czterech pozycji. We wszystkich metodach zastosowano korektę Holma. Pozycja 5 wykazała DIF jednorodny na korzyść osób starszych: Δ MH = 2.50 (kategoria C), ΔR² = .042, χ²(2) = 31.91, p < .001 w IRT. Pozycja 9 wykazała DIF niejednorodny w regresji logistycznej, χ²(2) = 27.65, p < .001, ΔR² = .026, oraz w IRT, χ²(2) = 25.85, p < .001 (dyskryminacja 2.01 u młodszych i 0.62 u starszych), ale nie w procedurze Mantela–Haenszela. Łączny wpływ DIF na wynik skali był niewielki (sDTF = −0.05 pkt, 95% CI [−0.10, −0.02]; uDTF = 0.16 pkt). Obie pozycje pozostawiono z parametrami swoistymi dla grup.

Jeśli recenzent pyta o DIF albo o porównywalność skali między grupami, możemy wspólnie zaplanować i sprawdzić analizę w ramach wsparcia statystycznego dla badaczy.

Przykład reprodukowalny

Przykład w R

Cztery przepisy uruchamiane po kolei w jednej sesji. Pierwszy tworzy dane i zapisuje plik dif-dane.csv (możesz go pobrać tutaj). Mantel–Haenszel i regresja logistyczna działają w bazowym R, a część IRT wymaga pakietu mirt.

1. Dane i procedura Mantela–Haenszela

Dane wejściowe: 1000 osób, 12 pozycji 0/1, grupa wiekowa (dane symulowane, set.seed(2170)); wbudowany DIF w p05 (jednorodny) i p09 (niejednorodny).

Co odczytać: M i SD wyniku ogólnego, a dla każdej pozycji χ²MH, p, αMH, ΔMH z SE, kategorię ETS i p po korekcie Holma – przed oczyszczeniem i po nim.

R
# Dane symulowane: lista 12 objawów depresyjnych (0 = nie, 1 = tak), młodsi (18–39 lat, grupa odniesienia)
# i starsi dorośli (60+, grupa ogniskowa), po 500 osób. Starsi mają średnio nieco wyższy poziom cechy (impact, nie DIF).
# Wbudowany DIF: p05 (wczesne budzenie się) – jednorodny; p09 (mniej energii) – niejednorodny.
set.seed(2170)
n <- 500
grupa <- factor(rep(c("mlodsi", "starsi"), each = n), levels = c("mlodsi", "starsi"))
theta <- c(rnorm(n, 0, 1), rnorm(n, 0.3, 1))
a <- c(1.4, 1.1, 1.7, 1.2, 1.3, 1.5, 1.0, 1.6, 1.4, 1.2, 1.8, 1.1)   # dyskryminacje (2PL)
b <- c(-0.8, -0.4, 0.0, 0.3, -0.2, 0.6, 0.9, 1.2, 0.2, 1.5, 0.4, 1.0)  # trudności (progi)
A <- matrix(a, 2 * n, 12, byrow = TRUE); B <- matrix(b, 2 * n, 12, byrow = TRUE)
starsi <- grupa == "starsi"
B[starsi, 5] <- b[5] - 0.7            # p05: starsi częściej odpowiadają „tak” przy tym samym θ
A[!starsi, 9] <- 1.9; A[starsi, 9] <- 0.6   # p09: inna dyskryminacja, krzywe się przecinają
X <- (matrix(runif(2 * n * 12), 2 * n) < plogis(A * (theta - B))) * 1L
colnames(X) <- sprintf("p%02d", 1:12)
write.csv(data.frame(id = 1:(2 * n), grupa, X), "dif-dane.csv", row.names = FALSE)

# Wynik ogólny w grupach (różnica średnich to jeszcze nie DIF)
wynik <- rowSums(X)
round(sapply(split(wynik, grupa), function(x) c(M = mean(x), SD = sd(x))), 2)

# Mantel–Haenszel dla pozycji j: warstwy = wynik dopasowujący (kotwice + badana pozycja)
mh_dif <- function(j, kotwice = colnames(X)) {
  dop <- rowSums(X[, union(kotwice, colnames(X)[j]), drop = FALSE])
  ok <- ave(dop, dop, FUN = length) > 1                     # warstwy z co najmniej 2 osobami
  tab <- table(grupa[ok], factor(X[ok, j], levels = 1:0), dop[ok])   # odniesienie × odpowiedź × warstwa
  t <- mantelhaen.test(tab)
  alfa <- unname(t$estimate)                                # wspólny iloraz szans MH
  s <- 2.35 * (log(t$conf.int[2]) - log(t$conf.int[1])) / (2 * qnorm(.975))   # SE delty
  d <- -2.35 * log(alfa)                                    # Δ MH w metryce ETS
  pA <- 2 * pnorm(-abs(d) / s)                              # H0: Δ = 0
  pC <- pnorm((-1 - abs(d)) / s) + pnorm((1 - abs(d)) / s)  # H0: |Δ| ≤ 1
  ets <- if (abs(d) <= 1 || pA >= .05) "A" else if (abs(d) >= 1.5 && pC < .05) "C" else "B"
  data.frame(pozycja = colnames(X)[j], chi2_MH = unname(t$statistic), p = t$p.value,
             alfa_MH = alfa, delta_MH = d, SE_delta = s, ETS = ets)
}
pokaz <- function(r) { r[sapply(r, is.numeric)] <- lapply(r[sapply(r, is.numeric)], round, 3); print(r, row.names = FALSE) }

# Krok 1: wszystkie pozycje w wyniku dopasowującym, korekta Holma
mh1 <- do.call(rbind, lapply(1:12, mh_dif)); mh1$p_Holm <- p.adjust(mh1$p, "holm"); pokaz(mh1)

# Krok 2: oczyszczanie – pozycje z istotnym DIF usuwamy z wyniku dopasowującego
kotwice_mh <- setdiff(colnames(X), mh1$pozycja[mh1$p_Holm < .05]); kotwice_mh
mh2 <- do.call(rbind, lapply(1:12, mh_dif, kotwice = kotwice_mh)); mh2$p_Holm <- p.adjust(mh2$p, "holm"); pokaz(mh2)
Wynik w R
   mlodsi starsi
M    4.90   5.85
SD   3.14   2.97
 pozycja chi2_MH     p alfa_MH delta_MH SE_delta ETS p_Holm
     p01   0.007 0.931   0.970    0.072    0.413   A  1.000
     p02   0.797 0.372   1.168   -0.365    0.374   A  1.000
     p03   2.556 0.110   1.311   -0.636    0.381   A  1.000
     p04   5.317 0.021   1.459   -0.888    0.373   A  0.232
     p05  40.369 0.000   0.345    2.498    0.400   C  0.000
     p06   0.032 0.858   0.960    0.096    0.373   A  1.000
     p07   0.687 0.407   0.870    0.326    0.360   A  1.000
     p08   0.598 0.439   1.181   -0.390    0.447   A  1.000
     p09   0.889 0.346   1.163   -0.356    0.353   A  1.000
     p10   0.011 0.916   1.035   -0.081    0.416   A  1.000
     p11   0.037 0.848   0.955    0.108    0.392   A  1.000
     p12   0.479 0.489   1.137   -0.302    0.393   A  1.000
 [1] "p01" "p02" "p03" "p04" "p06" "p07" "p08" "p09" "p10" "p11" "p12"
 pozycja chi2_MH     p alfa_MH delta_MH SE_delta ETS p_Holm
     p01   0.530 0.466   0.865    0.340    0.416   A      1
     p02   0.099 0.753   1.066   -0.149    0.378   A      1
     p03   0.506 0.477   1.137   -0.303    0.381   A      1
     p04   2.745 0.098   1.317   -0.647    0.373   A      1
     p05  40.369 0.000   0.345    2.498    0.400   C      0
     p06   0.532 0.466   0.880    0.300    0.372   A      1
     p07   1.537 0.215   0.818    0.471    0.360   A      1
     p08   0.121 0.728   1.089   -0.199    0.447   A      1
     p09   0.207 0.649   1.082   -0.185    0.354   A      1
     p10   0.014 0.907   0.964    0.086    0.416   A      1
     p11   1.114 0.291   0.826    0.449    0.393   A      1
     p12   0.074 0.786   1.061   -0.139    0.394   A      1

2. Regresja logistyczna: trzy modele zagnieżdżone

Dane wejściowe: te same odpowiedzi; wynik dopasowujący liczony z kotwic i badanej pozycji.

Co odczytać: listę kotwic po pierwszym przebiegu, łączny test 2 df (chi2_2df, p_2df), testy DIF jednorodnego i niejednorodnego, ΔR² Nagelkerkego, współczynniki grupy i interakcji, p po korekcie Holma i klasę efektu.

R
# Regresja logistyczna (Swaminathan i Rogers, 1990): trzy modele zagnieżdżone dla każdej pozycji
# M0: wynik dopasowujący; M1: + grupa (DIF jednorodny); M2: + interakcja (DIF niejednorodny)
r2_nagelkerke <- function(m) {
  N <- length(m$y)
  (1 - exp((m$deviance - m$null.deviance) / N)) / (1 - exp(-m$null.deviance / N))
}
lr_dif <- function(j, kotwice = colnames(X)) {
  y <- X[, j]
  s <- rowSums(X[, union(kotwice, colnames(X)[j]), drop = FALSE])
  m0 <- glm(y ~ s, family = binomial)
  m1 <- glm(y ~ s + grupa, family = binomial)
  m2 <- glm(y ~ s * grupa, family = binomial)
  data.frame(pozycja = colnames(X)[j],
             chi2_2df = m0$deviance - m2$deviance,
             p_2df = pchisq(m0$deviance - m2$deviance, 2, lower.tail = FALSE),
             p_jednorodny = pchisq(m0$deviance - m1$deviance, 1, lower.tail = FALSE),
             p_niejednorodny = pchisq(m1$deviance - m2$deviance, 1, lower.tail = FALSE),
             dR2_calk = r2_nagelkerke(m2) - r2_nagelkerke(m0),
             b_grupa = unname(coef(m1)["grupastarsi"]),
             b_interakcja = unname(coef(m2)["s:grupastarsi"]))
}
lr1 <- do.call(rbind, lapply(1:12, lr_dif)); lr1$p_Holm <- p.adjust(lr1$p_2df, "holm")
kotwice_lr <- setdiff(colnames(X), lr1$pozycja[lr1$p_Holm < .05]); kotwice_lr
# Oczyszczony wynik dopasowujący i klasyfikacja ΔR² według Jodoin i Gierla (2001)
lr2 <- do.call(rbind, lapply(1:12, lr_dif, kotwice = kotwice_lr)); lr2$p_Holm <- p.adjust(lr2$p_2df, "holm")
lr2$efekt <- cut(lr2$dR2_calk, c(-Inf, .035, .070, Inf), labels = c("pomijalny", "umiarkowany", "duży"), right = FALSE)
pokaz(lr2)
Wynik w R
 [1] "p01" "p02" "p03" "p04" "p06" "p07" "p08" "p10" "p11" "p12"
 pozycja chi2_2df p_2df p_jednorodny p_niejednorodny dR2_calk b_grupa
     p01    1.472 0.479        0.268           0.619    0.001   0.190
     p02    0.157 0.925        0.981           0.693    0.000   0.004
     p03    0.651 0.722        0.448           0.786    0.001  -0.122
     p04    3.961 0.138        0.058           0.538    0.004  -0.302
     p05   45.464 0.000        0.000           0.394    0.042   1.117
     p06    0.673 0.714        0.412           0.996    0.001   0.130
     p07    6.879 0.032        0.142           0.030    0.007   0.225
     p08    0.525 0.769        0.470           0.961    0.001  -0.137
     p09   27.652 0.000        0.933           0.000    0.026  -0.013
     p10    0.806 0.668        0.966           0.370    0.001  -0.008
     p11    4.223 0.121        0.187           0.115    0.004   0.221
     p12    1.508 0.470        0.680           0.247    0.001  -0.071
 b_interakcja p_Holm       efekt
        0.050  1.000   pomijalny
        0.031  1.000   pomijalny
        0.024  1.000   pomijalny
        0.050  1.000   pomijalny
        0.073  0.000 umiarkowany
        0.000  1.000   pomijalny
       -0.151  0.321   pomijalny
        0.005  1.000   pomijalny
       -0.363  0.000   pomijalny
        0.072  1.000   pomijalny
       -0.143  1.000   pomijalny
        0.097  1.000   pomijalny

3. IRT: kotwica, DIF() i DTF w pakiecie mirt

Dane wejściowe: te same odpowiedzi; model 2PL w dwóch grupach z wolną średnią i wariancją cechy u starszych.

Co odczytać: przegląd (χ², p, adj_p), wybrane kotwice, test właściwy, testy osobno dla dyskryminacji i progu, parametry a i b w grupach, statystyki sDTF i uDTF z 95% CI oraz oczekiwany wynik skali przy θ od −2 do 2.

R
# DIF w IRT: model 2PL w dwóch grupach (mirt), kotwice i testy ilorazu wiarygodności
suppressPackageStartupMessages(library(mirt))
# Krok 1: przegląd – każda pozycja testowana przy pozostałych jako kotwicach (schemat „drop”)
mg_wszystkie <- multipleGroup(X, 1, group = grupa, itemtype = "2PL",
                              invariance = c(colnames(X), "free_means", "free_var"), verbose = FALSE)
przeglad <- DIF(mg_wszystkie, which.par = c("a1", "d"), scheme = "drop", p.adjust = "holm", verbose = FALSE)
round(przeglad[, c("X2", "df", "p", "adj_p")], 3)

# Krok 2: kotwica = 4 pozycje najdalej od DIF w przeglądzie
kotwice_irt <- rownames(przeglad)[order(przeglad$p, decreasing = TRUE)][1:4]; kotwice_irt
mg_kotwice <- multipleGroup(X, 1, group = grupa, itemtype = "2PL",
                            invariance = c(kotwice_irt, "free_means", "free_var"), verbose = FALSE)
# Krok 3: pozostałe pozycje testowane po kolei przy ustalonej kotwicy (schemat „add”), korekta Holma
irt <- DIF(mg_kotwice, which.par = c("a1", "d"), scheme = "add",
           items2test = setdiff(colnames(X), kotwice_irt), p.adjust = "holm", verbose = FALSE)
round(irt[, c("X2", "df", "p", "adj_p")], 3)
# Który parametr się różni: osobno dyskryminacja (a1) i próg (d)
round(DIF(mg_kotwice, which.par = "a1", scheme = "add", items2test = c("p05", "p09"), verbose = FALSE)[, c("X2", "p")], 3)
round(DIF(mg_kotwice, which.par = "d", scheme = "add", items2test = c("p05", "p09"), verbose = FALSE)[, c("X2", "p")], 3)

# Model końcowy: parametry p05 i p09 swobodne w grupach, pozostałe wspólne
dif_irt <- rownames(irt)[irt$adj_p < .05]
mg_koniec <- multipleGroup(X, 1, group = grupa, itemtype = "2PL", SE = TRUE, verbose = FALSE,
                           invariance = c(setdiff(colnames(X), dif_irt), "free_means", "free_var"))
wsp <- coef(mg_koniec, IRTpars = TRUE, simplify = TRUE)
lapply(wsp, function(g) round(g$items[dif_irt, c("a", "b")], 2))
round(c(srednia_starsi = wsp$starsi$means[[1]], wariancja_starsi = wsp$starsi$cov[[1]]), 2)

# Skutek na poziomie testu (DTF): oczekiwany wynik 0–12 w grupach przy tym samym θ
set.seed(2171)
DTF(mg_koniec, draws = 500)
th <- matrix(c(-2, -1, 0, 1, 2))
round(sapply(c("mlodsi", "starsi"), function(g) expected.test(extract.group(mg_koniec, g), th)), 2)
Wynik w R
        X2 df     p adj_p
p01  1.849  2 0.397 1.000
p02  1.748  2 0.417 1.000
p03  5.624  2  0.06 0.541
p04  9.796  2 0.007 0.075
p05  41.83  2     0 0.000
p06   1.65  2 0.438 1.000
p07  2.834  2 0.242 1.000
p08  1.202  2 0.548 1.000
p09 29.581  2     0 0.000
p10  2.707  2 0.258 1.000
p11  0.324  2  0.85 1.000
p12  5.035  2 0.081 0.645
[1] "p11" "p08" "p06" "p02"
        X2 df     p adj_p
p01  1.087  2 0.581 1.000
p03  1.936  2  0.38 1.000
p04  5.231  2 0.073 0.439
p05 31.909  2     0 0.000
p07  3.539  2  0.17 0.852
p09 25.846  2     0 0.000
p10  1.525  2 0.467 1.000
p12  2.738  2 0.254 1.000
        X2    p
p05  0.159 0.69
p09 25.496    0
        X2     p
p05 29.129     0
p09  1.857 0.173
$mlodsi
       a     b
p05 1.46 -0.07
p09 2.01  0.26

$starsi
       a     b
p05 1.48 -0.84
p09 0.62  0.40

  srednia_starsi wariancja_starsi 
            0.28             0.97 
$observed
   sDTF.score sDTF(%).score    uDTF.score uDTF(%).score 
  -0.05380978   -0.44841487    0.15923570    1.32696418 

$CIs
         sDTF.score sDTF(%).score uDTF.score uDTF(%).score
CI_97.5 -0.01738326    -0.1448605  0.2637227     2.1976894
CI_2.5  -0.09805806    -0.8171505  0.1025310     0.8544254

$tests
P(sDTF.score = 0) 
      0.009074957 

     mlodsi starsi
[1,]   0.58   0.85
[2,]   1.82   2.28
[3,]   4.59   4.90
[4,]   8.17   8.05
[5,]  10.54  10.33

4. Zestawienie trzech metod

Dane wejściowe: wyniki przepisów 1–3 (uruchom je wcześniej w tej samej sesji).

Co odczytać: dla każdej pozycji ΔMH, kategorię ETS i p po korekcie z każdej metody; NA oznacza pozycję kotwiczącą, której IRT nie testuje.

R
# Porównanie trzech metod (po oczyszczeniu, korekta Holma, α = .05)
porownanie <- data.frame(pozycja = colnames(X),
  MH_delta = round(mh2$delta_MH, 2), MH_ETS = mh2$ETS, MH_p_Holm = round(mh2$p_Holm, 3),
  LR_dR2 = round(lr2$dR2_calk, 3), LR_p_Holm = round(lr2$p_Holm, 3),
  IRT_p_Holm = round(irt$adj_p[match(colnames(X), rownames(irt))], 3))
porownanie$IRT_p_Holm[is.na(porownanie$IRT_p_Holm)] <- NA   # kotwice nie są testowane
print(porownanie, row.names = FALSE)
Wynik w R
 pozycja MH_delta MH_ETS MH_p_Holm LR_dR2 LR_p_Holm IRT_p_Holm
     p01     0.34      A         1  0.001     1.000      1.000
     p02    -0.15      A         1  0.000     1.000         NA
     p03    -0.30      A         1  0.001     1.000      1.000
     p04    -0.65      A         1  0.004     1.000      0.439
     p05     2.50      C         0  0.042     0.000      0.000
     p06     0.30      A         1  0.001     1.000         NA
     p07     0.47      A         1  0.007     0.321      0.852
     p08    -0.20      A         1  0.001     1.000         NA
     p09    -0.18      A         1  0.026     0.000      0.000
     p10     0.09      A         1  0.001     1.000      1.000
     p11     0.45      A         1  0.004     1.000         NA
     p12    -0.14      A         1  0.001     1.000      1.000

Bibliografia oprogramowania

Wyniki na tej stronie pochodzą z uruchomienia pokazanego kodu w R 4.5.3 (funkcje mantelhaen.test(), glm(), p.adjust()) i w pakiecie mirt (funkcje multipleGroup(), DIF(), DTF()); rysunki przygotowano w pakiecie ggplot2.

  1. R: R Core Team. (2026). R: A language and environment for statistical computing (Version 4.5.3) [Computer software]. R Foundation for Statistical Computing. https://www.R-project.org/
  2. mirt (wersja 1.47): Chalmers, R. P. (2012). mirt: A multidimensional item response theory package for the R environment. Journal of Statistical Software, 48(6), 1–29. https://doi.org/10.18637/jss.v048.i06
  3. ggplot2 (wersja 4.0.2): Wickham, H. (2016). ggplot2: Elegant graphics for data analysis. Springer. https://ggplot2.tidyverse.org

Najczęstsze błędy

  • Różnica średnich pozycji uznana za DIF. Bez dopasowania na poziomie cechy mylisz DIF z rzeczywistą różnicą między grupami.
  • Tylko Mantel–Haenszel. DIF niejednorodny zostaje wtedy niewidoczny.
  • Brak oczyszczania i kotwica wybrana „na oko”. Pozycja z DIF w kotwicy przesuwa skalę i wywołuje pozorny DIF w innych pozycjach.
  • Same wartości p. W dużej próbie flagę dostaje każda drobna różnica, a w małej nawet duży DIF bywa nieistotny. Podawaj miarę efektu i DTF.
  • Automatyczne usuwanie pozycji. Decyzja wymaga analizy treści i oceny skutku dla skali (zob. przewodnik po psychometrii).

Najczęstsze pytania

Jak w R sprawdzić, czy DIF jest jednorodny, czy niejednorodny?

Dopasuj dla pozycji trzy modele glm(..., family = binomial): z samym wynikiem dopasowującym, z dodaną grupą i z interakcją wynik × grupa. Porównanie dwóch pierwszych testuje DIF jednorodny, a dwóch ostatnich niejednorodny (Swaminathan i Rogers, 1990). W mirt to samo pokażą osobne testy DIF() dla wyrazu wolnego d (próg) i dyskryminacji a1.

Czy metoda Mantela–Haenszela wykrywa DIF niejednorodny?

Zwykle nie. Wspólny iloraz szans uśrednia warstwy, więc gdy krzywe grup się przecinają, przewagi w różnych częściach skali się znoszą (Rogers i Swaminathan, 1993). W przykładzie pozycja z wyraźnym DIF niejednorodnym miała Δ MH = −0.18 i kategorię A. Uzupełnij więc MH regresją logistyczną albo IRT.

Jakie ΔR² oznacza istotny praktycznie DIF w regresji logistycznej?

Najczęściej stosuje się kryteria Jodoin i Gierla (2001): ΔR² poniżej .035 to DIF pomijalny, od .035 do .070 umiarkowany, a powyżej .070 duży. Starsze, wyższe progi uznano za zbyt mało czułe (Choi i in., 2011). Traktuj progi jako umowę i uzupełniaj je wykresem krzywych oraz oceną skutku dla całej skali.

Czy pozycję z DIF trzeba usunąć ze skali?

Nie automatycznie. Najpierw sprawdź treść pozycji i oceń łączny skutek DIF dla wyniku skali (DTF; Chalmers i in., 2016). Pozycję możesz usunąć, zostawić z parametrami swoistymi dla grup albo zostawić i opisać, gdy DIF jest pomijalny. Każdą decyzję uzasadnij w raporcie.

Czym różni się analiza DIF od testu inwariancji pomiaru w CFA?

Pytanie jest to samo: czy parametry pomiaru są równe w grupach. Nierówne ładunki odpowiadają DIF niejednorodnemu, a nierówne wyrazy wolne lub progi jednorodnemu. CFA zaczyna zwykle od całej skali, a DIF od pojedynczych pozycji. Przy tej samej strategii kotwicy obie metody działają podobnie dobrze (Stark i in., 2006).

Powiązane hasła

Przeczytaj też

Recenzent pyta, czy skala działa tak samo w porównywanych grupach?

Pomożemy zaplanować i przeprowadzić analizę DIF i inwariancji pomiaru, dobrać kotwicę i kryteria oraz wyjaśnić wyniki tak, żebyś mógł(a) je samodzielnie opisać i obronić.

Oferta dla badaczyPorozmawiaj o projekcie

Bibliografia i dalsza literatura naukowa (APA 7)

  1. Chalmers, R. P. (2012). mirt: A multidimensional item response theory package for the R environment. Journal of Statistical Software, 48(6), 1–29. https://doi.org/10.18637/jss.v048.i06 ● Otwarty dostęp
  2. Chalmers, R. P., Counsell, A., & Flora, D. B. (2016). It might not make a big DIF: Improved differential test functioning statistics that account for sampling variability. Educational and Psychological Measurement, 76(1), 114–140. https://doi.org/10.1177/0013164415584576 ● Otwarty dostęp: pełny tekst
  3. Choi, S. W., Gibbons, L. E., & Crane, P. K. (2011). lordif: An R package for detecting differential item functioning using iterative hybrid ordinal logistic regression/item response theory and Monte Carlo simulations. Journal of Statistical Software, 39(8), 1–30. https://doi.org/10.18637/jss.v039.i08 ● Otwarty dostęp
  4. Henninger, M., Debelak, R., & Strobl, C. (2023). A new stopping criterion for Rasch trees based on the Mantel–Haenszel effect size measure for differential item functioning. Educational and Psychological Measurement, 83(1), 181–212. https://doi.org/10.1177/00131644221077135 ● Otwarty dostęp
  5. Jodoin, M. G., & Gierl, M. J. (2001). Evaluating Type I error and power rates using an effect size measure with the logistic regression procedure for DIF detection. Applied Measurement in Education, 14(4), 329–349. https://doi.org/10.1207/s15324818ame1404_2
  6. Mantel, N., & Haenszel, W. (1959). Statistical aspects of the analysis of data from retrospective studies of disease. Journal of the National Cancer Institute, 22(4), 719–748. https://doi.org/10.1093/jnci/22.4.719
  7. Rogers, H. J., & Swaminathan, H. (1993). A comparison of logistic regression and Mantel-Haenszel procedures for detecting differential item functioning. Applied Psychological Measurement, 17(2), 105–116. https://doi.org/10.1177/014662169301700201 ● Otwarty dostęp: pełny tekst
  8. Stark, S., Chernyshenko, O. S., & Drasgow, F. (2006). Detecting differential item functioning with confirmatory factor analysis and item response theory: Toward a unified strategy. Journal of Applied Psychology, 91(6), 1292–1306. https://doi.org/10.1037/0021-9010.91.6.1292
  9. Swaminathan, H., & Rogers, H. J. (1990). Detecting differential item functioning using logistic regression procedures. Journal of Educational Measurement, 27(4), 361–370. https://doi.org/10.1111/j.1745-3984.1990.tb00754.x
  10. Zwick, R. (2012). A review of ETS differential item functioning assessment procedures: Flagging rules, minimum sample size requirements, and criterion refinement. ETS Research Report Series, 2012(1). https://doi.org/10.1002/j.2333-8504.2012.tb02290.x ● Otwarty dostęp

Cytowania BibTeX

@article{chalmers2012mirt, author={Chalmers, R. Philip}, title={{mirt: A multidimensional item response theory package for the R environment}}, journal={Journal of Statistical Software}, year={2012}, volume={48}, number={6}, pages={1--29}, doi={10.18637/jss.v048.i06}}
@article{chalmers2016might, author={Chalmers, R. Philip and Counsell, Alyssa and Flora, David B.}, title={{It might not make a big DIF: Improved differential test functioning statistics that account for sampling variability}}, journal={Educational and Psychological Measurement}, year={2016}, volume={76}, number={1}, pages={114--140}, doi={10.1177/0013164415584576}}
@article{choi2011lordif, author={Choi, Seung W. and Gibbons, Laura E. and Crane, Paul K.}, title={{lordif: An R package for detecting differential item functioning using iterative hybrid ordinal logistic regression/item response theory and Monte Carlo simulations}}, journal={Journal of Statistical Software}, year={2011}, volume={39}, number={8}, pages={1--30}, doi={10.18637/jss.v039.i08}}
@article{henninger2023new, author={Henninger, Mirka and Debelak, Rudolf and Strobl, Carolin}, title={{A new stopping criterion for Rasch trees based on the Mantel–Haenszel effect size measure for differential item functioning}}, journal={Educational and Psychological Measurement}, year={2023}, volume={83}, number={1}, pages={181--212}, doi={10.1177/00131644221077135}}
@article{jodoin2001evaluating, author={Jodoin, Michael G. and Gierl, Mark J.}, title={{Evaluating Type I error and power rates using an effect size measure with the logistic regression procedure for DIF detection}}, journal={Applied Measurement in Education}, year={2001}, volume={14}, number={4}, pages={329--349}, doi={10.1207/s15324818ame1404_2}}
@article{mantel1959statistical, author={Mantel, Nathan and Haenszel, William}, title={{Statistical aspects of the analysis of data from retrospective studies of disease}}, journal={Journal of the National Cancer Institute}, year={1959}, volume={22}, number={4}, pages={719--748}, doi={10.1093/jnci/22.4.719}}
@article{rogers1993comparison, author={Rogers, H. Jane and Swaminathan, Hariharan}, title={{A comparison of logistic regression and Mantel-Haenszel procedures for detecting differential item functioning}}, journal={Applied Psychological Measurement}, year={1993}, volume={17}, number={2}, pages={105--116}, doi={10.1177/014662169301700201}}
@article{stark2006detecting, author={Stark, Stephen and Chernyshenko, Oleksandr S. and Drasgow, Fritz}, title={{Detecting differential item functioning with confirmatory factor analysis and item response theory: Toward a unified strategy}}, journal={Journal of Applied Psychology}, year={2006}, volume={91}, number={6}, pages={1292--1306}, doi={10.1037/0021-9010.91.6.1292}}
@article{swaminathan1990detecting, author={Swaminathan, Hariharan and Rogers, H. Jane}, title={{Detecting differential item functioning using logistic regression procedures}}, journal={Journal of Educational Measurement}, year={1990}, volume={27}, number={4}, pages={361--370}, doi={10.1111/j.1745-3984.1990.tb00754.x}}
@article{zwick2012review, author={Zwick, Rebecca}, title={{A review of ETS differential item functioning assessment procedures: Flagging rules, minimum sample size requirements, and criterion refinement}}, journal={ETS Research Report Series}, year={2012}, volume={2012}, number={1}, doi={10.1002/j.2333-8504.2012.tb02290.x}}
R