4 Erste psychometrische Auswertungen

Dieses Kapitel arbeitet einige Kennwerte der klassischen Testtheorie auf und bespricht wie wir diese in R berechnen können. Dabei werden die folgenden Konzepte behandelt:

  • Summenwerte
  • Item-Schwierigkeit
  • Item-Trennschärfe
  • Item-Interkorrelation
  • Reliabilität
    • Interne Konsistenz („Cronbachs Alpha“)
    • Split-Half/Odd-Even-Reliabilität
  • Spearman-Brown-Formel

Angenommen, eine Datentabelle enthält die Punktzahlen von zehn Schulkindern in einer Klassenarbeit mit fünf Aufgaben. Diese kann man gut in einer \(10 \times 5\) (Reihe \(\times\) Spalten) Datentabelle darstellen. Ein Eintrag kodiert, ob das Kind (Reihe) die Aufgabe (Spalte) korrekt gelöst hat. Korrekte Antworten werden mit 1 kodiert, falsche Antworten mit 0 – ein typisches Datenformat in der psychologischen Diagnostik. Wenn uns Daten in diesem Format vorliegen, können wir auf viele Funktionen in R zurückgreifen, um grundlegende psychometrische Auswertungen durchzuführen. Dies sind etwa die Bestimmung der Schwierigkeit und der Trennschärfe von Items, sowie die Bestimmung einer Split-Half Reliabilität. Für fortgeschrittenere Auswertungen – wie etwa die Berechnung von Cronbachs Alpha oder einer Faktorenanalyse – werden wir auf Pakete zurückgreifen, die uns über die Basics in R hinaus weitere Funktionalitäten bieten. Aber auch für diese Analysen benötigen wir genau dieses Datenformat!

Um das fortführende Beispiel selbst nachzuvollziehen, muss der folgende data.frame eingelesen werden:

Merke: Das ist das Standard-Datenformat für all unsere psychometrischen Berechnungen: (a) Zeilen sind Fälle; (b) Spalten sind Items bzw. Messvariablen; (c) Zellen enthalten Datenpunkte, etwa die Korrektheit von Antworten (kodiert mit 1/0). Datenpunkte müssen nicht unbedingt – wie es in diesem Beispiel der Fall ist – dichotom sein, sondern können beispielsweise auch die Antworten in einem Persönlichkeitsfragebogen auf einer Likert-Skala repräsentieren.

4.1 Summenwerte

Wir bestimmen zunächst die Testscores der 10 Kinder. Da jede Zeile ein Kind repräsentiert, ist der Gesamt-Testscore die Summe der Werte in jeder Reihe. Die Summe der Reihen (engl: rows) eines data.frames können wir mit der Funktion rowSums() bestimmen:

 [1] 4 1 5 0 3 1 2 1 3 0

Es ist manchmal praktisch Berechnungen, die pro Fall einen Wert ergeben, direkt an den ursprünglichen data.frame anzuhängen. Wie in Kapitel 3 erklärt, ist das mit der $-Notation möglich:

   Item_1 Item_2 Item_3 Item_4 Item_5 score
1       1      0      1      1      1     4
2       1      0      0      0      0     1
3       1      1      1      1      1     5
4       0      0      0      0      0     0
5       0      0      1      1      1     3
6       0      0      1      0      0     1
7       1      0      1      0      0     2
8       1      0      0      0      0     1
9       1      0      1      1      0     3
10      0      0      0      0      0     0

Da viele viele Analysen aber nur einen data.frame mit den Item-Spalten benötigt (\(\to\) psychometrisches Standardformat), ist hier Vorsicht bei der Weiterverwendung geboten!

4.2 Item-Schwierigkeiten

Die Schwierigkeit eines Items ist die mittlere Punktzahl aller Personen in diesem Item. Auch bei Items, die nicht Korrektheit kodieren, kann man von Item-Schwierigkeit sprechen. Beispielsweise wäre dann die Item-Schwierigkeit die mittlere Zustimmungsrate für ein Item in einem Persönlichkeitsinventar, in dem Antworten auf einer 5-stufigen Likert-Skala gegeben werden. Hierbei macht die Einteilung in hohe vs.  niedrige Schwierigkeit wenig Sinn; technisch gesehen bedeuten immer niedrigere Werte eine höhere Schwierigkeit (also etwa eine niedrige Zustimmungsrate).

Technisch gesehen ist die Schwierigkeit eines Items der Mittelwert der Itemwerte in einer Spalte (engl: column) eines data.frames im psychometrischen Standardformat. Den Mittelwert pro Spalte kann ich mit der Funktion colMeans() bestimmen (analog gibt es auch die Funktionen colSums() und rowMeans()):

Item_1 Item_2 Item_3 Item_4 Item_5  score 
   0.6    0.1    0.6    0.4    0.3    2.0 

Da ich gerade den Gesamtscore als Spalte an test_data angehängt habe, bekomme ich die mittlere Punktzahl der Schüler/innen in den fünf Testitems direkt mitgeliefert.

Die Funktion colMeans() generalisiert die Funktion mean() von einem einzelnen Vektor auf alle Spalten in einem data.frame. Beachtet: Würde der data.frame auch Spalten vom Typ factor oder character enthalten, wäre es nicht möglich, Funktionen wie rowSums() und colMeans() darauf anzuwenden. Hier muss jede Spalte einen numerischen Vektor enthalten.

4.3 Item-Interkorrelationen

Als Nächstes geben wir mit der Funktion cor() die Korrelationen zwischen allen Items als Korrelationsmatrix aus. Wenn cor() als Argument einen data.frame erhält, wird eine Tabelle ausgegeben, die die Korrelation zwischen allen Spalten – d.h. Items – des data.frames enthält.

       Item_1 Item_2 Item_3 Item_4 Item_5 score
Item_1   1.00   0.27   0.17   0.25   0.09  0.51
Item_2   0.27   1.00   0.27   0.41   0.51  0.62
Item_3   0.17   0.27   1.00   0.67   0.53  0.76
Item_4   0.25   0.41   0.67   1.00   0.80  0.89
Item_5   0.09   0.51   0.53   0.80   1.00  0.81
score    0.51   0.62   0.76   0.89   0.81  1.00

Die Korrelationen wurden aus Darstellungszwecken mit der Funktion round() auf zwei Nachkommastellen gerundet. Die Ausgabe der Funktion cor() ist eine Tabelle, die alle Korrelationen zwischen den Items (und auch mit dem Gesamtscore) abbildet. Beachtet, dass die Matrix symmetrisch ist, also die Korrelation zwischen Item 1 und Item 2 natürlich der Korrelation zwischen Item 2 und Item 1 entspricht. Auf der Diagonalen befindet sich immer eine 1, da jedes Item perfekt mit sich selbst korreliert. Die ausgegebene Tabelle erinnert an einen data.frame, ist aber technisch gesehen eine andere Datenstruktur, nämlich eine Matrix. Der Unterschied zwischen Matritzen und data.frames soll uns jedoch zunächst nicht kümmern.

4.3.1 Exkurs: Programmatische Untersuchung der Korrelationsmatrix

Große Item-Korrelationsmatritzen sind oftmals unübersichtlich und erschweren den Überblick darüber, welche Items stärker oder weniger stark miteinander korrelieren. Eine visuelle Inspektion ist demnach mühsam und fehleranfällig. Stattdessen würden wir lieber programmatisch die Eigenschaften der Korrelationsmatrix erforschen. Glücklicherweise ist dies mit R möglich, da die Korrelationsmatrix selbst nur ein R-Objekt ist und wir beliebig damit arbeiten können.

Typischerweise weiß man beispielsweise gerne, welche zwei Items am stärksten miteinander korrelieren. Um dieser Frage nachzugehen, lernen wir in diesem Abschnitt, dass vektorisierte R-Funktionen im Normalfall nicht nur auf einfachen Vektoren agieren (siehe Kapitel 2), sondern sich auch auf komplexere Strukturen wie eine Korrelationsmatrix übertragen lassen.

Speichern wir zunächst die Item-Korrelationsmatrix in einer Variablen ab. Dabei achten wir darauf, die Korrelation zum Summenscore aus der Korrelationsmatrix zu entfernen; es interessieren uns nur die Korrelationen zwischen den einzelnen Items (der nächste Abschnitt behandelt die Bedeutung der Korrelationen zwischen Items und Summenscore):

Zunächst stellen wir fest, dass logische Operationen auf Korrelationsmatritzen anwendbar sind. Wir können so etwa feststellen, welche Items stärker als zu r = .50 miteinander korrelieren:

       Item_1 Item_2 Item_3 Item_4 Item_5
Item_1   TRUE  FALSE  FALSE  FALSE  FALSE
Item_2  FALSE   TRUE  FALSE  FALSE   TRUE
Item_3  FALSE  FALSE   TRUE   TRUE   TRUE
Item_4  FALSE  FALSE   TRUE   TRUE   TRUE
Item_5  FALSE   TRUE   TRUE   TRUE   TRUE

Die Ausgabe ist eine logische Matrix, die für jedes Itempaar kodiert, ob die Korrelation zwischen diesen Items größer ist als r = .50. Bei Item 5 und Item 2 ist dies beispielsweise der Fall. Eine solche logische Matrix kann jedoch gerade bei vielen Items unübersichtlich werden. Wir können mit der Funktion which() herausfinden, welche Items mit mehr als r = .50 miteinander korrelieren:

       row col
Item_1   1   1
Item_2   2   2
Item_5   5   2
Item_3   3   3
Item_4   4   3
Item_5   5   3
Item_3   3   4
Item_4   4   4
Item_5   5   4
Item_2   2   5
Item_3   3   5
Item_4   4   5
Item_5   5   5

Da wir hier eine Matrix und nicht einen Vektor untersuchen, müssen wir das Argument arr.ind = TRUE setzen, um eine sinnvolle Ausgabe zu erhalten. Besonders übersichtlich ist diese Ausgabe jedoch immer noch nicht, da sie auch alle “Autokorrelationen” markiert – also die Diagonale der Korrelationsmatrix, die die Korrelation jedes Items mit sich selbst abbildet. Dies wollen wir vermeiden. Eine Möglichkeit ist es, die Diagonale der Korrelationsmatrix anzupassen. Auch hier verwenden wir eine Operation, die wir im Kapitel zu Vektoren kennengelernt haben und die auch auf Matritzen generalisiert:

       Item_1 Item_2 Item_3 Item_4 Item_5
Item_1     NA   0.27   0.17   0.25   0.09
Item_2   0.27     NA   0.27   0.41   0.51
Item_3   0.17   0.27     NA   0.67   0.53
Item_4   0.25   0.41   0.67     NA   0.80
Item_5   0.09   0.51   0.53   0.80     NA

Wir ersetzen auf diese Weise alle Einsen der Korrelationsmatrix durch einen fehlenden Wert; danach können wir per which() einfacher erfragen, welche Korrelationen größer als r = .50 sind:

       row col
Item_5   5   2
Item_4   4   3
Item_5   5   3
Item_3   3   4
Item_5   5   4
Item_2   2   5
Item_3   3   5
Item_4   4   5

Noch besser wird die Ausgabe, wenn wir die Redundanz aus der Korrelationsmatrix entfernen; schließlich befinden sich im oberen und unteren Dreieck der Matrix dieselben Informationen. Wir können die Korrelationen oben rechts durch Verwendung der Funktion upper.tri()24 durch NA ersetzen:

       Item_1 Item_2 Item_3 Item_4 Item_5
Item_1     NA     NA     NA     NA     NA
Item_2   0.27     NA     NA     NA     NA
Item_3   0.17   0.27     NA     NA     NA
Item_4   0.25   0.41   0.67     NA     NA
Item_5   0.09   0.51   0.53    0.8     NA
       row col
Item_5   5   2
Item_4   4   3
Item_5   5   3
Item_5   5   4

Item 5 korreliert also stark mit den Items 2, 3 und 4, und Item 3 korreliert noch stark mit Item 4.

Mit einem ähnlichen Vorgehen können wir programmatisch – ohne visuelle Inspektion – bestimmen, zwischen welchen Items die stärkste Korrelation besteht. Hier wenden wir zunächst die Funktion max() auf die Korrelationsmatrix an:

[1] 0.8017837

Beachtet, dass diese Operation nicht sinnvoll gewesen wäre, wenn die Autokorrelationen auf der Diagonalen noch enthalten gewesen wären. Nun können wir durch eine logische Abfrage und die Funktion which() bestimmen, zwischen welchen Items die stärkste Korrelation besteht:

       row col
Item_5   5   4

Am stärksten korrelieren also die Items 4 und 5 miteinander. Zugegeben, das hätten wir im Falle von 5 Items auch einfach durch Betrachten der Korrelationsmatrix erfassen können, aber gerade bei sehr großen Test-Inventaren ist die programmatische Untersuchung einer Korrelationsmatrix einer visuellen Inspektion gegenüber deutlich zu bevorzugen.

4.4 Item-Trennschärfen

Interessant ist die letzte Spalte (bzw. genauso die letzte Zeile) der obigen Korrelationsmatrix:

       Item_1 Item_2 Item_3 Item_4 Item_5 score
Item_1   1.00   0.27   0.17   0.25   0.09  0.51
Item_2   0.27   1.00   0.27   0.41   0.51  0.62
Item_3   0.17   0.27   1.00   0.67   0.53  0.76
Item_4   0.25   0.41   0.67   1.00   0.80  0.89
Item_5   0.09   0.51   0.53   0.80   1.00  0.81
score    0.51   0.62   0.76   0.89   0.81  1.00

Diese gibt an, wie stark die Korrelation zwischen jedem Item und dem Testscore ausfällt. Dieser Kennwert ist die (unkorrigierte) Trennschärfe der Items; wir erhalten sie, da wir oben den Testscore als Spalte an unseren data.frame angehängt haben. Die Item-Trennschärfe macht eine Aussage darüber, wie stark das Abschneiden in einem Item mit dem Gesamt-Testscore zusammenhängt. Je höher die Trennschärfe, desto besser vermag das Item zwischen Schüler/innen mit viel und wenig Wissen (also einem hohen bzw. einem niedrigen Gesamt-Testscore) zu trennen. Die Trennschärfe ist ein Kennwert, der zur Beurteilung der Güte eines Items dienen kann.

Oftmals wird die „part-whole“ korrigierte Trennschärfe berechnet, bei der zur Berechnung der Trennschärfe jedes Items der Itemscore dieses Items aus der Gesamtpunktzahl ausgelassen wird. Somit wird eine „Kriterienkontamination“ vermieden, die zu einer Erhöhung der Trennschärfe führt. Diese Kriterienkontamination ergibt sich bei der unkorrigierten Trennschärfe daraus, dass der Itemscore selbst in das „Kriterium“ – also den Gesamt-Testscore – eingeht.25 Im Folgenden berechnen wir eine part-whole korrigierte Trennschärfe für Item 2. Zunächst erstelle ich einen Vektor zur Auswahl der Items, die ich zur Berechnung des Testscores unter Ausschluss von Item 2 heranziehe:

  Item_1 Item_3 Item_4 Item_5
1      1      1      1      1
2      1      0      0      0
3      1      1      1      1
4      0      0      0      0
5      0      1      1      1
6      0      1      0      0

Die Variable corrected_score enthält nun die Testscores, die unter Ausschluss des zweiten Items gebildet wurden. Das Vorgehen zur Berechnung der bereinigten Scores lässt sich mithilfe der [·,·]-Notation und den Funktionen paste0() und rowSums() auch auf beliebig viele Items erweitern. Da wir hier den Summenwert nur über vier Items gebildet haben, hätte auch der folgende Code funktioniert:

Wie folgt können wir nun mithilfe der Funktion cor() die korrigierte Trennschärfe für Item 2 bestimmen:

[1] 0.4842001

Die korrigierte Trennschärfe von 0.48 liegt unter der unkorrigierten Trennschärfe von 0.62. Je weniger Items ein Test hat, desto mehr Gewicht hat das einzelne Item für den Testscore und umso stärker weichen korrigierte und unkorrigierte Trennschärfe voneinander ab. Bei nur fünf Items kann der Effekt substantiell sein.

Es ist zu beachten, dass die Funktion cor() an dieser Stelle anders verwendet wird als oben: Hier übergebe ich der Funktion cor() mit dem Befehl cor(test_data$Item_2, corrected_score) zwei Vektoren gleicher Länge. Ein Vektor enthält die Korrektheiten der Antworten auf Item 2, der andere Vektor enthält den um Item 2 bereinigten Testscore. Oben habe ich der Funktion cor() nur ein Argument übergeben, nämlich den data.frame test_data. In dem Fall wurde eine Tabelle ausgegeben – eine Korrelationsmatrix –, die die Korrelationen zwischen allen Spalten enthält.

Ich empfehle den Code-Block zur Berechnung der korrigierten Trennschärfe genau zu studieren. Darin finden sich viele der Grundlagen aus Kapitel 2 und 3 wieder:

  • Die Erstellung von Vektoren mit der 1:n-Notation
  • Die Negativ-Auswahl von Elementen aus Vektoren mit der [·]-Notation
  • Die Generierung eines Vektors vom Typ character mit der Funktion paste0()
  • Die Auswahl von Spalten in einem data.frame mit der [·,·]-Notation

Wir merken, dass es mühsamer ist, die korrigierte Trennschärfe zu berechnen als die unkorrigierte. Die unkorrigierte Trennschärfe erhielt ich oben einfach, indem ich einen ganzen data.frame an die Funktion cor() übergeben habe. Ich musste nur einen einzigen Funktionsaufruf – oder eine Zeile Code – investieren. Um jedoch die korrigierte Trennschärfe zu bestimmen, muss ich bei n Items n Mal einen korrigierten Gesamtscore berechnen. Für jedes Item muss ich dann jeweils das Item mit diesem korrigierten Score korrelieren. Wenn wir das für jedes Item „händisch“ machen würden, wäre das sehr aufwendig (beispielsweise könnten wir den Code oben n Mal kopieren und jeweils die Itemnummern anpassen – das wäre sehr fehleranfällig). Einer der Hauptgründe aus denen wir R lernen ist, dass wir uns solche Arbeit nicht machen wollen. Stattdessen wollen wir lernen, wie wir repetitive Arbeiten automatisieren können. In Kapitel 7 lernen wir Schleifen kennen, die uns ermöglichen, ohne wesentlich mehr Aufwand für beliebig viele Items korrigierte Trennschärfen zu bestimmen.

4.5 Cronbachs Alpha

Als Nächstes bestimmen wir „Cronbachs Alpha“ als Maß für die interne Konsistenz der Antworten der Schüler/innen. Cronbachs Alpha ist ein Schätzer für die Reliabilität eines Tests. Im Falle eines Leistungstest mit dichotomer Bepunktung gibt es eine Antwort auf die Frage: Haben Kinder, die ein Item richtig beantworten, auch eine erhöhte Wahrscheinlichkeit, andere Items richtig zu beantworten? (Ebenso: haben Kinder, die ein Item falsch beantworten, auch eine erhöhte Wahrscheinlichkeit, andere Items falsch zu beantworten?). Je näher Cronbachs Alpha an 1 ist, desto stärker ist das der Fall – desto stärker ist die interne Konsistenz der Punktwerte. Ein Wert von 0 spricht dafür, dass gar keine Systematik in den Punktzahlen liegt – ob ich viele oder wenig Punkte bekommen habe, ist gänzlich zufällig.

R bietet in der Grundversion keine Möglichkeit, Cronbachs Alpha zu bestimmen. Man könnte sich eine eigene Berechnung programmieren, die Cronbachs Alpha umsetzt.26 Wir machen uns aber zunutze, dass bereits andere R-Nutzer Cronbachs Alpha als Funktion umgesetzt haben, und diese in einem Paket zur Verfügung gestellt haben. Eine Umsetzung von Cronbachs Alpha findet sich im Paket psych (Revelle, 2019). Mit der Funktion library() kann ich Pakete laden, die nicht zur Grundausstattung von R gehören. Voraussetzung ist, dass ich das Paket auf meinem Rechner installiert habe. Die Erweiterbarkeit durch Pakete ist eine der großen Stärken von R.

Falls das Paket nicht installiert ist, kann ich es mit dem folgenden Befehl installieren:

Praktischerweise arbeitet die Funktion alpha() aus dem psych Paket genau mit dem Standard-Datenformat, das uns vorliegt: Zeilen kennzeichnen Testteilnehmer, Spalten kennzeichnen Items. Wichtig ist aber nun: Wir haben soeben den Testscore als zusätzliche Spalte an die Testdatentabelle angehängt. Diese geht aber nicht in die Berechnung von Cronbachs Alpha ein, sondern nur die Punktzahlen für die Items. Deswegen entferne ich die Spalte score wie folgt wieder:

[1] "Item_1" "Item_2" "Item_3" "Item_4" "Item_5"

Wir haben gelernt, dass wir Variablen mit der Funktion rm() löschen können. Wir können sie aber nicht nutzen, wenn wir Spalten aus data.frames entfernen wollen. Das liegt daran, dass die Spalte selber keine Variable ist, sondern zu einem data.frame gehört. Deswegen muss man Spalten mit dem Befehl data.frame$spalte <- NULL entfernen. NULL ist in R ein Wert, der für „Nicht-Existenz“ steht.

Nachdem wir das Paket psych geladen und die Spalte score entfernt haben, können wir Cronbachs Alpha mit der Funktion alpha() bestimmen:


Reliability analysis   
Call: alpha(x = test_data)

  raw_alpha std.alpha G6(smc) average_r S/N  ase mean   sd median_r
      0.76      0.77     0.8       0.4 3.3 0.12  0.4 0.34     0.34

    95% confidence boundaries 
         lower alpha upper
Feldt     0.40  0.76  0.93
Duhachek  0.53  0.76  0.99

 Reliability if an item is dropped:
       raw_alpha std.alpha G6(smc) average_r S/N alpha se var.r med.r
Item_1      0.82      0.82    0.82      0.53 4.5    0.082 0.035  0.52
Item_2      0.74      0.74    0.77      0.42 2.9    0.136 0.084  0.39
Item_3      0.70      0.72    0.75      0.39 2.5    0.156 0.062  0.34
Item_4      0.61      0.64    0.63      0.31 1.8    0.201 0.032  0.27
Item_5      0.66      0.67    0.66      0.34 2.1    0.170 0.032  0.27

 Item statistics 
        n raw.r std.r r.cor r.drop mean   sd
Item_1 10  0.51  0.49  0.29   0.23  0.6 0.52
Item_2 10  0.62  0.68  0.55   0.48  0.1 0.32
Item_3 10  0.76  0.73  0.65   0.57  0.6 0.52
Item_4 10  0.89  0.87  0.89   0.78  0.4 0.52
Item_5 10  0.81  0.82  0.82   0.67  0.3 0.48

Non missing response frequency for each item
         0   1 miss
Item_1 0.4 0.6    0
Item_2 0.9 0.1    0
Item_3 0.4 0.6    0
Item_4 0.6 0.4    0
Item_5 0.7 0.3    0

Wir sehen, dass die Funktion alpha() viel Output mit Informationen zum übergebenen Item-Datensatz generiert und uns nicht nur den Wert für Cronbachs Alpha zurückgibt. Dieser kann unter raw_alpha abgelesen werden und beträgt 0.76.

4.6 Split-Half-Reliabilität

Cronbachs Alpha ist ein Schätzer für die Reliabilität eines Tests. Andere mögliche Schätzer sind die Retest-Reliabilität und die Split-Half-Reliabilität. Diese basieren auf der Berechnung einer Korrelation zwischen zwei Punktwerten. Für die Bestimmung der Retest-Reliabilität lassen wir Testteilnehmer zweimal denselben Test bearbeiten und korrelieren die Punktwerte, die sich zu den zwei Testzeitpunkten ergeben.

Noch leichter ist die Bestimmung der Split-Half-Reliabilität, welche nicht das mehrmalige Bearbeiten desselben Tests erfordert. Dabei teilen wir die Items des Tests in zwei Gruppen ein und bilden Summenwerte für die beiden Testhälften, welche wir dann miteinander korrelieren. Wir müssen dabei berücksichtigen, dass wir nur die Hälfte des Tests zur Schätzung der Reliabilität verwenden. Dies kann mithilfe der Spearman-Brown-Formel korrigiert werden.

Die Spearman-Brown-Formel schätzt die Reliabilität eines Tests für den hypothetischen Fall, dass man diesen um einen bestimmten Faktor verlängern würde (d.h. man würde die bestehenden Items replizieren). Man kann sie verwenden, um den Reliabilitätsschätzer einer Split-Half-Korrelation zu korrigieren, da in diesen nur die Hälfte der Items eingehen. Die Spearman-Brown Formel ist diese:

\[r' = \frac{r \, n}{1 + (n - 1) r}\]

Hierbei ist r’ die um die Testlänge korrigierte Reliabilität. r ist der derzeitige Reliabilitätsschätzer, also beispielsweise die Korrelation von zwei Testhälften. n ist der Faktor, um den der Test hypothetisch verlängert wird. Für die Schätzung der Split-Half-Reliabilität muss man einen Verlängerungsfaktor von 2 annehmen, da man die Reliabilität nur mit einem halbierten Test schätzt (im Vergleich dazu geht bei der Bestimmung der Retest-Reliabilität zweimal der gesamte Test in die Korrelation ein).

Um die spearman-brown-korrigierte Split-Half-Reliabilität zu schätzen, teilen wir zunächst die Items in zwei Mengen auf; hier ist es nicht möglich gleich große Teile zu generieren, also wählen wir die ersten drei und die letzten zwei Items aus:

Als nächstes berechnen wir die Korrelation zwischen den beiden Testhälften:

[1] 0.6049383

Nun wollen wir diese Korrelation mit der Spearman-Brown-Formel korrigieren. Zu diesem Zweck definieren wir eine eigene Funktion, die die Spearman-Brown-Formel umsetzt. An dieser Stelle reicht es aus, das Konzept einer eigenen Funktion zur Kenntnis zu nehmen – es wird in Kapitel 6 wieder aufgegriffen:

Wenn wir die Funktion definiert haben – das heißt: den Funktions-Code in der Konsole ausgeführt haben –, können wir sie wie andere bekannte Funktionen aufrufen. Wir müssen zwei Argumente angeben: (1) Unseren initialen Schätzer der Reliabilität, also die Korrelation zwischen den zwei Testhälften; (2) den Verlängerungsfaktor, hier 2, da wir die Reliabilität für die doppelte Testlänge schätzen wollen:

[1] 0.7538462

Wie wir sehen, liegt die Spearman-Brown-korrigierte Split-Half-Reliabilität näher an Cronbachs Alpha (0.76) als die unkorrigierte Korrelation der zwei Testhälften. Das liegt daran, dass die Korrelation der zwei Testhälften die Reliabilität systematisch unterschätzt, da dieser Schätzer nur auf der Hälfte der Items beruht. Es ist sogar so, dass Cronbachs Alpha genau der Mittelwert aller möglichen Spearman-Brown korrigierten Split-Half-Koeffizienten ist.

Alternativ hätten wir auch die Odd-Even-Reliabilität berechnen können, die die Testitems in gerade und ungerade Items einteilt, also hier zwei Testscores einerseits für die Items 1, 3 und 5, und andererseits für die Items 2 und 4 berechnet. Diese lässt sich mit nur wenig Änderungen am Code oben umsetzen – ich schlage vor, dies als Übung zu machen.

4.7 In der Praxis: Nutzung von Zusatzpaketen

In der praktischen psychometrischen Auswertung werden wir oftmals auf externe Pakete zurückgreifen, um Berechnungen durchzuführen. Insbesondere die selbst programmierte Berechnung der korrigierten Trennschärfe war, wie oben vorgestellt, recht mühsam und fehleranfällig. Außerdem ergab sie erst einmal nur eine einzige Trennschärfe. Idealerweise hätten wir aber durch nur einen Funktionsaufruf direkt die Trennschärfen aller Items eines Tests bestimmt.

Zu diesem Zweck greifen wir noch einmal auf das Paket psych zurück. Wie wir im Abschnitt zu Cronbachs Alpha gesehen haben, gibt die Funktion alpha() nicht nur den Wert von Cronbachs Alpha zurück, sondern führt gleich noch eine ganze Reihe weiterer Berechnungen für den Item-Datensatz durch, der ihr übergeben wird. Darunter befinden sich auch die unkorrigierten und korrigierten Item-Trennschärfen. Im Output können wir eine Tabelle Item-Kennwerten betrachten:

        n raw.r std.r r.cor r.drop mean   sd
Item_1 10  0.51  0.49  0.29   0.23  0.6 0.52
Item_2 10  0.62  0.68  0.55   0.48  0.1 0.32
Item_3 10  0.76  0.73  0.65   0.57  0.6 0.52
Item_4 10  0.89  0.87  0.89   0.78  0.4 0.52
Item_5 10  0.81  0.82  0.82   0.67  0.3 0.48

Die Spalte mit der Überschrift raw.r beinhaltet die unkorrigierten Trennschärfen der Items, die Spalte mit der Überschrift r.drop beinhaltet die korrigierten Trennschärfen. Für Item 2 wird dieselbe (hier gerundete) korrigierte Trennschärfe ausgegeben, die wir oben im Abschnitt zu Item-Trennschärfen per Hand berechnet haben. Interessant ist auch die Spalte n, die noch einmal aufführt, auf der Basis wievieler Item-Teilnahmen die Werte berechnet wurden.

Insgesamt ist das Paket psych ein wichtiges R-Zusatzpaket für psychometrische Auswertungen. Der Autor des psych-Pakets (William Revelle) stellt außerdem auf seiner Website (https://personality-project.org/r/psych/) hilfreiche Materialien für die psychometrische Auswertung in R zur Verfügung. Dazu gehört auch ein ganzes Buch zur psychometrischen Datenauswertung (http://www.personality-project.org/r/book/).


  1. Wer mehr zur Manipulation von Matritzen lernen möchte, kann eine Recherche zu den Funktionen upper.tri(), lower.tri() und diag() durchführen.

  2. Praktisch gesehen werden unkorrigierte und korrigierte Trennschärfe dieselbe relative Rangreihe zwischen den Items hinsichtlich ihrer Diskriminationsgüte abbilden.

  3. Das wäre sogar eine gute Übung. Die Formel findet sich unter https://de.wikipedia.org/wiki/Cronbachs_Alpha