Faktoren in R: der Datentyp factor
In der Statistik steht man oft vor der Aufgabe, eine Reihe von Messdaten zu klassifizieren (oder: gruppieren) und die gruppierten Daten weiter auszuwerten (etwa Häufigkeiten der Klassen feststellen, Mittelwertbildung innerhalb der Klassen). Man kann diese Operationen natürlich auf der Ebene von Vektoren durchführen, indem man geeignete Funktionen für Vektoren anwendet. In R gibt es den Datentyp factor, der die Klassifizierung vornimmt und zahlreiche Auswertungen deutlich vereinfacht. Vorgestellt werden hier zuerst die Begriffe aus der Statistik, die mit der Klassifizierung von Daten zusammenhängen; weiter wie Faktoren und geordnete Faktoren erzeugt werden sowie deren Eigenschaften. Im folgenden Kapitel werden dann Anwendungen mit Faktoren gezeigt.
- Einordnung des Artikels
- Einführung
- Klassifizierung von Daten: Merkmalstypen
- Einige Begriffe aus der Statistik: Stichprobe, Merkmal, Merkmalstyp
- Charakterisierung der verschiedenen Merkmalstypen
- Der nominale Merkmalstyp
- Der ordinale Merkmalstyp
- Der diskrete Merkmalstyp
- Der stetige Merkmalstyp
- Faktoren (factor) und geordnete Faktoren (ordered)
- Einführung
- Erzeugen von ungeordneten Faktoren
- Erzeugen von geordneten Faktoren
- Eigenschaften von Faktoren
- Faktor als Kodierung eines Vektors
- Die Funktion tabulate(): Abzählen, wie oft Zahlen in einem Vektor (oder Faktor) vorkommen
- Die Attribute eines Faktors: levels und class
- Abfrage der Levels
- Veränderung der Levels
- Die Bedeutung der Klasse
- Diagnose-Funktionen für Faktoren
- Weitere Funktionen zum Erzeugen von Faktoren
- as-dot-Funktionen
- Erzeugen von regelmäßigen Faktoren mit der Funktion gl()
- Zusammenfassung
- Funktionen zum Erzeugen von Faktoren und geordneten Faktoren
- Eigenschaften von (geordneten) Faktoren
Einordnung des Artikels
- Einführung in die Informatik
- Einführung in die Programmiersprache R
- Zusammengesetzte Datentypen in R
- Faktoren in R: der Datentyp factor
- Faktoren in R: Anwendungen
- Zusammengesetzte Datentypen in R
- Einführung in die Programmiersprache R
Einführung
Die bisher vorgestellten zusammengesetzten Datentypen wie Vektoren, Felder, Listen oder Data Frames kann man auch als Container auffassen: sie dienen dazu, Tupel von Zahlen (oder Zeichenketten) nach gewissen Regeln abzuspeichern. Je nachdem welcher innere Zusammenhang zwischen den Komponenten besteht und wie man sie weiterverarbeiten möchte, wird man den einen oder anderen Container auswählen. Mit Faktoren wird ein Container angeboten, der schon eine Auswertung beinhaltet: Die Daten werden gruppiert (oder wie man auch sagt: in Klassen eingeteilt) – so wie etwa jedem Datum ein bestimmter Wochentag zugeordnet werden kann.
Um kennenzulernen wie Faktoren in R realisiert werden, erklären dieses und das folgende Kapitel (Faktoren in R: Anwendungen):
- Statistische Begriffe zur Definition von Klassen.
- Wie definiert man Faktoren und geordnete Faktoren in R?
- Welche Eigenschaften besitzen Faktoren?
- Welche Funktionen stellt R bereit, um Faktoren zur Weiterverarbeitung von Daten einzusetzen?
Fortgeführt wird die Untersuchung der Faktoren mit:
- dem Kapitel über Faktoren in R: Anwendungen und
- dem Kapitel über Tabellen (table), die eng mit Faktoren verknüpft sind.
Klassifizierung von Daten: Merkmalstypen
Einige Begriffe aus der Statistik: Stichprobe, Merkmal, Merkmalstyp
Bei einer statistischen Untersuchung wird üblicherweise eine Stichprobe genommen, wobei deren Objekte (oder Merkmalsträger) auf eine gewisses Merkmal hin untersucht werden. Die Merkmalsträger unterscheiden sich eigentlich in vielerlei Hinsicht, für die Stichprobe ist aber nur das untersuchte Merkmal relevant. In diesem Sinne wird durch die Auswahl eines Merkmals eine Klassifizierung der Merkmalsträger vorgenommen; sie werden in Klassen eingeteilt, wobei gilt:
- Für jeden Merkmalsträger gibt es eine Klasse.
- Jeder Merkmalsträger wird in nur eine Klasse eingeteilt.
Ein bekanntes Beispiel ist die Sonntagsfrage:
Welche Partei würden Sie wählen, wenn am nächsten Sonntag Wahlen wären?
Die Objekte oder Merkmalsträger der Stichprobe sind hier die befragten Wahlberechtigten und das Merkmal, das untersucht wird, ist die Partei, die voraussichtlich gewählt wird. Als Grundgesamtheit würde man hier alle Personen bezeichnen, die für die Befragung ausgewählt werden können (vermutlich alle Wahlberechtigten). Das Merkmal kann nur bestimmte Werte annehmen, nämlich die zur Wahl zugelassenen Parteien, etwa A, B, C, D, E; vermutlich wird man noch eine weitere Klasse wie unentschieden anbieten. Man nennt diese Menge der möglichen Werte des Merkmals die Merkmalsausprägung.
Das zu untersuchende Merkmal kann verschiedene Typen besitzen, die als Merkmalstyp bezeichnet werden. Ihre grobe Einteilung ist in Abbildung 1 zu sehen. Die weiter unten folgenden Beispiele werden zeigen, dass die Abgrenzung zwischen den verschiedenen Merkmalstypen schwieriger ist als es zunächst erscheint.
Charakterisierung der verschiedenen Merkmalstypen
Der nominale Merkmalstyp
Im Beispiel der Sonntagsfrage oben liegt offensichtlich ein qualitativer Merkmalstyp vor, da es kaum möglich ist, eine Partei quantitativ – also durch eine geeignete Kennzahl – zu beschreiben. Die Menge der möglichen Werte des Merkmals wurde mit A, B, C, D, E bezeichnet, was eine Anordnung suggeriert. Auch neigt man dazu, Parteien in einer gewissen Richtung (von rechts nach links oder umgekehrt) anzuordnen. Bei genauerer Betrachtung sind diese Anordnungen aber nicht möglich und sie zeigen nur die Vorurteile, mit der man an eine Umfrage herangeht. Richtig ist, dass das Merkmal, das bei der Sonntagsfrage untersucht wird qualitativ und nominal ist. Dabei soll nominal gerade ausdrücken, dass die Werte durch Worte und nicht durch Zahlen beschrieben werden und eben nicht angeordnet werden können.
Andere typische Beispiele für qualitative, nominale Merkmale sind:
- Blutgruppe
- Geschlecht
- Unterteilung einer Art in Unterarten (wie Früchte werden unterteilt in Äpfel, Birnen, Kirschen und so weiter)
- Berufe.
Der Begriff nominal soll – wie gesagt – hier ausdrücken, dass man das Merkmal nur mit Worten treffend beschreiben kann, aber nicht mit Zahlen. Man kann zwar Zahlen immer als Abkürzung verwenden und so spricht eigentlich nichts dagegen, anstelle der Bezeichnungen A, B, C, D, E für die Parteien die Zahlen 1, 2, 3, 4, 5 zu verwenden. Aber die Zahlen suggerieren, dass die Merkmalsausprägungen angeordnet und quantifiziert werden können und man verschleiert den nominalen Charakter des Merkmals. Dies kann dazu führen, dass womöglich unsinnige Berechnungen durchgeführt werden, etwa: Die Sonntagsfrage ergab, dass im Durchschnitt die Partei 2.7 gewählt wird! Bei einem nominalen Merkmalstyp sollten daher Zahlen nicht verwendet werden.
Der ordinale Merkmalstyp
Ist dagegen bei einem qualitativen Merkmalstyp eine Anordnung möglich, spricht man von einem ordinalen Merkmalstyp.
Beispiele hierfür sind:
- Schulnoten,
- Plazierung in einem Turnier,
- Abschluss einer Ausbildung.
Schulnoten werden entweder in Worten formuliert, in der Abstufung sehr gut, gut, befriedigend, ausreichend, mangelhaft und ungenügend oder sie werden mit den Zahlen von 1 bis 6 abgekürzt. Die Verwendung von Zahlen ist hier wieder sehr irreführend, weil sie suggerieren, dass der Abstand zweier Noten immer gleich ist.
Man kann dies vielleicht besser am Beispiel der Plazierung in einem Turnier erläutern.
Beispiel:
4 Mannschaften A, B, C, D spielen ein Fußball-Turnier, wobei jeder gegen jeden spielt. Die Rangfolge sei:
Plazierung | Mannschaft |
1 | A |
2 | B |
3 | C |
4 | D |
Tabelle 1: Rangfolge der 4 Mannschaften bei einem Turnier nach dem Modus jeder gegen jeden.
Es ist klar, dass A die beste Mannschaft ist, B die zweitbeste Mannschaft und so weiter. Kennt man die Rangfolge, ist man aber auch geneigt zu sagen, dass die Leistungsdifferenzen zwischen den Mannschaften identisch sind. Dies kann man aber aus der Rangfolge allein nicht ablesen. Denn es sind verschiedene Detail-Ergebnisse möglich, wie die beiden folgenden Tabellen zeigen:
Plazierung | Mannschaft | Punkte | Tordifferenz |
1 | A | 9 | 6 |
2 | B | 2 | -1 |
3 | C | 2 | -2 |
4 | D | 2 | -3 |
Tabelle 2: Die Mannschaft A ist hier die eindeutig überlegene Mannschaft, die anderen drei Mannschaften sind nahezu gleich stark.
Plazierung | Mannschaft | Punkte | Tordifferenz |
1 | A | 9 | 3 |
2 | B | 6 | 1 |
3 | C | 3 | -1 |
4 | D | 0 | -3 |
Tabelle 3: Jetzt verbergen sich hinter den Plazierungen deutliche Leistungsdifferenzen der vier Mannschaften.
In Tabelle 2 ist Mannschaft A das klar beste Team und hat die drei anderen Mannschaften besiegt. Dagegen sind B, C und D nahezu gleich stark, da sie untereinander unentschieden gespielt haben. Die Rangfolge untereinander entsteht nur dadurch, dass sie unterschiedlich hoch gegen A verloren haben.
In Tabelle 3 dagegen hat jede Mannschaft gegen die nachfolgend plazierten Mannschaften gewonnen, aber gegen die höher plazierten Mannschaften verloren (jedes Spiel endete mit einem Tor Differenz). In diesem Fall ist eine klare Leistungsdifferenz zwischen den Mannschaften durch das Turnier-Ergebnis zu erkennen – dass die Leistungsdifferenzen tatsächlich identisch sind, sollte man aber auch nicht folgern.
Etwas abstrakter formuliert, bedeutet eine Ordnungsrelation, dass zwischen je zwei beliebig ausgewählten Merkmalsträgern eine Ordnung hergestellt werden kann, die die Eigenschaften des ≤-Zeichens besitzen:
- Für zwei Elemente a, b gilt entweder a ≤ b oder b ≤ a.
- Ist a ≤ b und b ≤ c, so ist a ≤ c.
Man beachte aber, dass man auch beim ordinalen Merkmalstyp sehr gut Zahlen einsetzen kann, da diese eine offensichtliche Anordnung besitzen. Aber wie beim nominalen Merkmalstyp suggeriert ihre Verwendung, dass man auch sinnvolle Differenzen bilden kann – am Beispiel des Fußball-Turniers wurde gezeigt, dass der Unterschied zwischen Platz 1 und 2 in der Tabelle manchmal einer sehr großen Leistungsdifferenz entspricht (siehe Tabelle 2; sehr groß heißt hier: groß im Vergleich zu den Leistungsdifferenzen zwischen den zweit- bis viertplazierten Mannschaften), manchmal einer eher kleinen Leistungsdifferenz entspricht (Tabelle 3; streng genommen kann man hier aus dem Ergebnis nichts über die Leistungsdifferenzen aussagen!).
Auch bei der Beurteilung der Schul-Leistungen suggeriert die Verwendung von Zahlen mehr als eine Anordnung: Die Differenz zwischen den Noten 6 und 5 ist identisch zur Differenz zwischen den Noten 2 und 1. Aber lassen sich solche Differenzen wirklich vergleichen? Jeder Schüler hat wohl irgendwann die Erfahrung gemacht: Hat man seine Leistungsgrenze erreicht, kann man sich mit noch so viel Aufwand nicht mehr verbessern – die Schwelle zur nächstbesseren Note scheint unüberwindbar zu sein. Die Interpretation der Noten-Differenzen als gleich große Abstände zwischen den Leistungsstufen suggeriert hingegen, dass man mit dem selben Mehraufwand, mit dem man sich um eine Notenstufe verbessert, immer wieder um eine weitere Notenstufe verbessern kann.
Noch deutlicher wird die suggestive Kraft der Verwendung von Zahlen bei einem qualitativen Merkmalstyp, wenn man anstelle der Schulnoten 1, 2, 3, 4, 5, 6 die sechs Notenstufen 1, 4, 5, 8, 9, 10 verwendet. Die Noten sind immer noch angeordnet, es sind immer noch 6 verschiedene Noten, aber ihre unterschiedlichen Abstände suggerieren eine völlig andere Bedeutung als die üblichen Noten von 1 bis 6.
In den beiden folgenden Unterabschnitten werden die quantitativen Merkmalstypen besprochen, die sich dadurch auszeichnen, dass jetzt Zahlen sinnvoll eingesetzt werden können, da man ihre Abstände inhaltlich interpretieren kann.
Der diskrete Merkmalstyp
Falls man ein Merkmal derart mit Zahlen beschreiben kann, dass man die Differenzen sinnvoll vergleichen kann, spricht man von einem quantitativen Merkmalstyp. Abstrakter formuliert, bilden die Zahlen zur Beschreibung des Merkmals eine Metrik.
Sind nur ganze Zahlen zugelassen, spricht man von einem diskreten Merkmalstyp, der kontinuierliche (oder stetige) Merkmalstyp wird dann im folgenden Unterabschnitt besprochen.
Ein Paradebeispiel für einen diskreten Merkmalstyp ist die Anzahl, wie oft ein Produkt A in einem Warenkorb enthalten ist. Dabei soll das Produkt so beschaffen sein, dass man es nicht teilen kann (also nicht etwa in beliebiger Menge nach Gewicht einkaufen kann). Hier sind also zur Beschreibung eines Einkaufs die Null und die natürlichen Zahlen geeignet: 0, 1, 2, ...
Der stetige Merkmalstyp
Wird ein Produkt nach Gewicht eingekauft, sind im Prinzip alle positiven Zahlen geeignet, um den Einkauf zu charakterisieren. Man spricht von einem stetigen (oder kontinuierlichen) Merkmalstyp.
In der Praxis wird man aber die Zahlen nicht mit beliebiger Genauigkeit angeben – wer verfügt schon über eine Waage, die auf Milligramm genau oder noch genauer wägen kann? Streng genommen ist man somit wieder bei einem diskreten Merkmalstyp (durch Multiplikation mit einem geeigneten Faktor kann man auch wieder ganze Zahlen erzeugen).
Faktoren (factor) und geordnete Faktoren (ordered)
Einführung
Nach dem kleinen Exkurs in die Statistik sollte klar geworden sein, wie wichtig dort eine Klassifizierung (oder Kategorisierung) der Messergebnisse ist. In einer Stichprobe können niemals alle Eigenschaften der Merkmalsträger aufgenommen werden, vielmehr werden die Merkmalsträger in Klassen eingeteilt.
Eine besonders einfache derartige Einteilung wird in der Mathematik vorgenommen, wenn zum Beispiel die ganzen Zahlen in sogenannte Restklassen eingeteilt werden: Man gibt sich eine Basis, zum Beispiel 7, vor und bildet für jede Zahl n den Rest bei einer Division durch 7. Dieser Rest kann nur die Werte 0, 1, 2, ..., 6 annehmen. Somit kann man jeder Zahl n eindeutig einen Rest r zuordnen: die Zahl 50 wird zum Beispiel auf 1 abgebildet, da 50 = 49 + 1.
Verwendet wird diese Restklassenbildung bei der Einteilung des Kalenders in Wochen und Tage: In 50 Tagen ist derselbe Wochentag wie morgen, da im Sinne der Restklassen 50 und 1 gleichwertig sind – anders gesagt: demselben Wochentag entsprechen.
In der Algebra werden derartige Konstrukte als Quotientenklassen oder Faktorklassen bezeichnet. In R wird der Datentyp, der die Einteilung in mehrere Klassen ermöglicht, als Faktor bezeichnet. Genauer: man spricht von einem Faktor (factor), wenn es sich um einen nominalen, also nicht geordneten Merkmalstyp handelt und von einem geordneten Faktor (ordered factor) bei einem ordinalen Merkmalstyp.
In den folgenden Abschnitten werden die Eigenschaften der Faktoren genauer untersucht. Auf den ersten Blick ist ein Faktor ein character-Vektor, der zu einer gegebenen Stichprobe einen Vektor identischer Länge erzeugt, wobei jede Komponente angibt, in welcher Klasse die entsprechende Komponente der Stichprobe liegt. Da character-Vektoren sehr viel Speicherplatz benötigen, werden die Klassen intern als Zahlen gespeichert – und zum souveränen Umgang mit Faktoren sollte man weitere Spitzfindigkeiten kennen.
Die wichtigste Funktion für Faktoren ist table(): mit kann aus dem Vektor, der für eine Stichprobe steht, sofort berechnet werden, wie oft jede Klasse in der Stichprobe vorkommt.
Erzeugen von ungeordneten Faktoren
Als erstes Beispiel wird die Sonntagsfrage von oben verwendet. Bei einer Stichprobe werden 20 Wahlberechtigte befragt; das Ergebnis ist im Vektor sample gespeichert. Dabei soll keiner der Befragten die Partei "D" angeben. Der Vektor sample wird verwendet, um einen Faktor zu erzeugen.
Die einfachste Art, wie ein Faktor erzeugt wird, ist die Übergabe des Vektors mit der Stichprobe an die Funktion factor(); diese hat eigentlich noch weitere Argumente, die im ersten Beispiel noch nicht besprochen werden.
sample <- c("A", "A", "E", "C", "B", "A", "E", "C", "A", "E", "C", "B", "A", "B", "E", "C", "A", "B", "E", "C")
length(sample) # 20
sample
# [1] "A" "A" "E" "C" "B" "A" "E" "C" "A" "E" "C" "B" "A" "B" "E" "C" "A" "B" "E" "C"
mode(sample) # [1] "character"
sf <- factor(x = sample)
sf
# [1] A A E C B A E C A E C B A B E C A B E C
# Levels: A B C E
table(sf)
# sf
# A B C E
# 6 4 5 5
is.vector(sf) # FALSE
is.list(sf) # FALSE
is.factor(sf) # TRUE
is.ordered(sf) # FALSE
length(sf) # 20
Das Skript zeigt die wichtigsten Eigenschaften eines Faktors, ist aber an einigen Stellen erklärungsbedürftig:
Zeile 1 und 2: Es wird ein Vektor namens sample erzeugt, der die Länge 20 besitzt und dessen Komponenten Zeichen sind.
Zeile 4 und 5: Die Ausgabe dieses Vektors zeigt die Komponenten als Zeichen (Anführungsstriche).
Zeile 7: Bestätigt nochmals, dass die Komponenten von sample Zeichen sind (character mode).
Zeile 9: Die Funktion factor() wird in der einfachsten Form aufgerufen, indem ihr der Vektor x = sample übergeben wird; es werden keine anderen Argumente gesetzt. Aus x wird ein Faktor namens sf erzeugt (sf kann für sample factor oder Sonntagsfrage stehen). Mit den folgenden Ausgaben werden die Eigenschaften des Faktors sf untersucht.
Zeile 10 bis 12: Die Ausgabe des Faktors sf hat zwei Teile. Zum einen wird für die 20 Komponenten des Vektors sample gezeigt, zu welcher Klasse sie gehören (Zeile 11). Zum anderen werden diese Levels aufgelistet (Zeile 12). Man beachte, dass in Zeile 11 keine Anführungsstriche stehen – der Faktor sieht also nur auf den ersten Blick wie ein Vektor aus Zeichen aus! Intern werden die Levels natürlich – um Speicherplatz zu sparen – als Zahlen gespeichert. Und in Zeile 12 fehlt die Partei D: klar, da sie nicht in der Stichprobe enthalten war.
Zeile 14 bis 17: Die für die Auswertung von Stichproben wichtigste Funktion ist table(), an die der Faktor übergeben wird. Ausgegeben wird dann der Name des Faktors (Zeile 15), die Levels (Zeile 16) und ihnen zugeordnet die Häufigkeit ihres Vorkommens in sample (Zeile 17).
Zeile 19 bis 25: Mit den weiteren Ausgaben wird der Faktor näher untersucht. Man erkennt, dass ein Faktor weder ein Vektor noch eine Liste ist. Die Ausgabe des Faktors sf in Zeile 11 erinnert sehr an einen Vektor, an Zeile 19 erkennt man aber ausdrücklich, dass sf kein Vektor ist. (Man könnte auch Zeile 9 derart missverstehen, dass ein Faktor ein spezieller Vektor ist.) Aber es gibt eine Abfrage für seinen Datentyp mit is.factor() (in Zeile 21). Wie für alle R-Objekte ist die Länge eines Faktors definiert und stimmt mit der Länge des zugrundeliegenden Vektors sample überein (Zeile 25 und Zeile 2).
Aus der Sicht der Statistik sind zwei Punkte noch zu diskutieren:
- Der Faktor sf ist nicht geordnet. Wie oben erläutert wurde, ist dies richtig so, denn der Merkmalstyp ist nominal (und nicht ordinal). Die Ausgabe von sf zeigt aber die Levels in der richtigen alphabetischen Reihenfolge – man könnte also argwöhnen, dass die Levels intern angeordnet werden. Ebenso zeigt die Tabelle, die durch table(sf) erzeugt wird, die Levels in alphabetischer Reihenfolge. Nach Zeile 23 ist aber sf kein geordneter Faktor. Wie man geordnete Faktoren erzeugt, wird weiter unten gezeigt.
- Aus der Sicht der Statistik ist die Vorgehensweise etwas fraglich: Denn es wird zuerst der Vektor der Stichprobe sample erzeugt und anschließend werden durch Definition des Faktors die Levels festgelegt (wobei dies intern durch den Aufruf der Funktion factor() geschieht). Naheliegender ist es eigentlich, vor dem Aufnehmen der Stichprobe die Levels festzulegen. In diesem Fall sind es ja 5 Levels und die Stichprobe ist – zufällig – von der Art, dass Level "D" nicht vorkommt. Und die Ausgabe mittels table() sollte 5 Levels anzeigen.
Nach dem letzten Punkt, sollte es auch möglich sein, zuerst die Levels zu definieren und anschließend den Faktor zu erzeugen. Dies geschieht mit einem weiteren Argument in der Funktion factor(). Dort kann man ausdrücklich die Levels setzen:
sf_lev <- factor(x = sample, levels = c("A", "B", "C", "D", "E"))
sf_lev
# [1] A A E C B A E C A E C B A B E C A B E C
# Levels: A B C D E
table(sf_lev)
# sf_lev
# A B C D E
# 6 4 5 0 5
is.ordered(sf_lev) # FALSE
Man beachte, dass man die Levels tatsächlich als Zeichenkette setzen muss (Zeile 1 im Argument levels = c("A", "B", "C", "D", "E")
). Die Ausgabe des Faktors (Zeile 2 bis 4) und der Häufigkeiten der Levels (mit table(), Zeile 6 bis 9) zeigt jetzt 5 Levels, obwohl Level "D" in der Stichprobe nicht vorkommt. Geordnet ist der Faktor immer noch nicht (Zeile 11).
Oben bei der Vorstellung der Begriffe nominaler und ordinaler Merkmalstyp wurde argumentiert, dass es gefährlich ist, für die Levels Zahlen einzusetzen, weil dies zu Fehlinterpretationen führen kann. Um zu untersuchen, wie R numerische Levels behandelt, wird das Beispiel der Sonntagsfrage nochmals durchgespielt – mit dem Unterschied, dass die Parteien durch Zahlen abgekürzt werden ("A" = 1, "B" = 2, und so weiter). Auch hier könnte man argwöhnen, dass – da die Zahlen geordnet sind – intern ein geordneter Faktor erzeugt wird. Das folgende Skript untersucht dies:
sample <- c(1 , 1, 5, 3, 2, 1, 5, 3, 1, 5, 3, 2, 1, 2, 5, 3, 1, 2, 5, 3)
length(sample) # 20
sample
# [1] 1 1 5 3 2 1 5 3 1 5 3 2 1 2 5 3 1 2 5 3
mode(sample) # [1] "numeric"
sf <- factor(x = sample)
# sf[1] 1 1 5 3 2 1 5 3 1 5 3 2 1 2 5 3 1 2 5 3
# Levels: 1 2 3 5
table(sf)
# sf
# 1 2 3 5
# 6 4 5 5
is.vector(sf) # FALSE
is.list(sf) # FALSE
is.factor(sf) # TRUE
is.ordered(sf) # FALSE
length(sf) # 20
Man erkennt an den Ausgaben, dass tatsächlich nur die Levels anders kodiert wurden – es wurde kein geordneter Faktor erzeugt.
Erzeugen von geordneten Faktoren
Um einen geordneten Faktor zu erzeugen, gibt es mehrere Möglichkeiten; die einfachste besteht darin, in der Funktion factor() das weitere Argument ordered = TRUE
anzugeben, wie es das folgende Beispiel zeigt:
sf_ord <- factor(x = sample, ordered = TRUE)
sf_ord
# [1] A A E C B A E C A E C B A B E C A B E C
# Levels: A < B < C < E
is.ordered(sf_ord) # TRUE
Man kann dann sogar selbst bestimmen, in welcher Reihenfolge die Levels angeordnet werden. Dazu muss man nur die Levels in der gewünschten Reihenfolge selber setzen, wie im folgenden Beispiel zu sehen ist:
sf_ord <- factor(x = sample, levels = c("E", "D", "C", "B", "A"), ordered = TRUE)
sf_ord
# [1] A A E C B A E C A E C B A B E C A B E C
# Levels: E < D < C < B < A
table(sf_ord)
# sf_ord
# E D C B A
# 5 0 5 4 6
Entsprechend der Reihenfolge, in der die Levels eingegeben wurden (im Argument levels = c("E", "D", "C", "B", "A")
, Zeile 1), werden sie im Faktor verwendet (Zeile 4).
Auch in der Ausgabe mit table() wird diese Reihenfolge beachtet (Zeile 6 bis 9).
Es gibt noch eine weitere Möglichkeit, einen geordneten Faktor zu erzeugen: nämlich mit der Funktion ordered(), bei der es nicht nötig ist, ausdrücklich ein weiteres Argument zu setzen, das eine Reihenfolge der Levels herstellt:
sf_ord <- ordered(x = sample)
sf_ord
# [1] A A E C B A E C A E C B A B E C A B E C
# Levels: A < B < C < E
is.ordered(sf_ord) # TRUE
table(sf_ord)
# sf_ord2
# A B C E
# 6 4 5 5
Wie bei der Funktion factor() werden die Levels aus der Stichprobe abgelesen – mit dem Unterschied, dass sie geordnet sind.
Möchte man die Levels schon vorher setzen, geschieht dies wie bei der Funktion factor(); man kann auch die Reihenfolge der Levels selbst bestimmen:
sf_ord <- ordered(sample, levels = c("E", "D", "C", "B", "A"))
sf_ord
# [1] A A E C B A E C A E C B A B E C A B E C
# Levels: E < D < C < B < A
table(sf_ord)
# sf_ord
# E D C B A
# 5 0 5 4 6
Setzt man die Levels selbst, kann es passieren, dass in der Stichprobe ein Wert enthalten ist, der nicht in den Levels vorkommt. Führt dies zu einem Syntax-Fehler oder zu einer Ausgabe, die auf den fehlenden Level hinweist? Im folgenden Skript wird die Stichprobe der Sonntagsfrage verwendet, aber der Level "E" wird nicht gesetzt, anschließend werden der Faktor und die Tabelle der Häufigkeiten der Levels ausgegeben:
sample <- c("A", "A", "E", "C", "B", "A", "E", "C", "A", "E", "C", "B", "A", "B", "E", "C", "A", "B", "E", "C")
sf <- factor(x = sample, levels = c("A", "B", "C", "D"))
sf
# [1] A A <NA> C B A <NA> C A <NA> C B A B <NA> C A B <NA>
# [20] C
table(sf)
# sf
# A B C D
# 6 4 5 0
An der Ausgabe des Faktors erkennt man, dass die Komponenten, in denen in sample der Wert "E" vorkam, jetzt mit NA (Not Available) belegt werden (Zeile 3 bis 5).
Bei der Ausgabe der Häufigkeiten (Zeile 7 bis 10) ist auf den ersten Blick keine Unstimmigkeit zu erkennen. Erst wenn man die Häufigkeiten addiert, sieht man, dass ihre Summe nicht 20, also die Länge des Vektors sample, ergibt. Bei einer Weiterverarbeitung der Häufigkeiten der Levels muss man dies bedenken!
Wie oben soll auch hier nochmals das Beispiel der Sonntagsfrage untersucht werden, wenn die Parteien durch Zahlen abgekürzt werden; im Unterschied zu oben wird aber ordered = TRUE
gesetzt. Das folgende Skript zeigt die Eigenschaften dieses Faktors:
sample <- c(1 , 1, 5, 3, 2, 1, 5, 3, 1, 5, 3, 2, 1, 2, 5, 3, 1, 2, 5, 3)
length(sample) # 20
sample
# [1] 1 1 5 3 2 1 5 3 1 5 3 2 1 2 5 3 1 2 5 3
mode(sample) # [1] "numeric"
sf_ord <- factor(x = sample, ordered = TRUE)
sf_ord
# [1] 1 1 5 3 2 1 5 3 1 5 3 2 1 2 5 3 1 2 5 3
# Levels: 1 < 2 < 3 < 5
is.ordered(sf_ord) # TRUE
Eigenschaften von Faktoren
Faktor als Kodierung eines Vektors
Das Beispiel der Sonntagsfrage soll jetzt unter einem anderen Gesichtspunkt betrachtet werden: Bisher wurden nämlich Faktoren vor allem unter dem Aspekt betrachtet, dass sich damit Klassen (die Levels) definieren lassen, wenn Daten gruppiert werden sollen. Man kann einen Faktor auch so verstehen, dass mit ihm ein gegebener Vektor x kodiert wird, wobei kodieren hier nicht so zu lesen ist, dass sich der ursprüngliche Vektor x eindeutig rekonstruieren lässt, vielmehr kann (durch die Bildung von Klassen) ein Teil der Information verloren gehen.
Im folgenden Beispiel wird nochmal zum Ergebnis der Sonntags-Umfrage sample und gegebenen Klassen (die 5 Parteien) ein Faktor gebildet:
sample <- c("A", "A", "E", "C", "B", "A", "E", "C", "A", "E", "C", "B", "A", "B", "E", "C", "A", "B", "E", "C")
length(sample) # 20
lev <- c("A", "B", "C", "D", "E")
sf_lev <- factor(x = sample, levels = lev)
sf_lev
# [1] A A E C B A E C A E C B A B E C A B E C
# Levels: A B C D E
length(sf_lev) # 20
is.vector(sf_lev) # FALSE
mode(sf_lev) # "numeric"
storage.mode(sf_lev) # "integer"
Im Beispiel werden der Vektor sample (der Länge 20) und die Levels (hier als Vektor lev mit den 5 Levels für die 5 Parteien, Zeile 4) erzeugt, womit der ungeordnete Faktor sf_lev definiert wird (Zeile 6). Die Ausgabe des Faktors zeigt die 20 Ergebnisse der Stichprobe (Zeile 8) sowie die 5 Levels (Zeile 9).
Die weiteren Ausgaben zeigen, dass der Faktor zwar eine Länge von 20 besitzt, aber kein Vektor ist (Zeile 11 und 12); und dass es sich um 20 Zahlen handelt (Zeile 13), genauer im Speichermodus integer (Zeile 14). Laut der Ausgabe in Zeile 8 waren eher Zeichen (character) zu erwarten.
Man sollte sich einen Faktor als eine Kodierung eines Vektors x vorstellen: In der Funktion factor() wird der gegebene Vektor x = sample mit Hilfe der Levels auf Zahlen abgebildet. Wenn n Levels vorliegen (hier n = 5), werden zur Kodierung des Vektors x die Zahlen 1, 2,..., n verwendet. Genauer: Der Vektor sample wird komponentenweise untersucht, also samplei, i = 1, 2,..., 20 betrachtet. Stimmt eine der Komponenten von sample
mit lev[j]
überein, j = 1, 2,..., 5:
sample[i] == lev[j]
so wird im Faktor an der Stelle i die Zahl j gespeichert; somit entsteht ein Vektor der Länge 20, der nur die Zahlen 1, 2,..., 5 enthält:
A A E C B A E C A E C B A B E C A B E C
1 1 5 3 2 1 5 3 1 5 3 2 1 2 5 3 1 2 5 1
Da in den meisten Fällen die Länge des Vektors x sehr viel größer ist als die Anzahl n der Levels, benötigt man sehr viel weniger Speicherplatz, wenn der Vektor mit Zahlen und nicht den eigentlichen Levels kodiert wird. Um die Ausgabe wie in Zeile 7 oben zu erzeugen, muss man einmal die Zuordnung der Levels zu den Zahlen 1, 2,..., n herstellen – und diese verbirgt sich hinter Zeile 9.
Nach außen sind die intern verwendeten Zahlen aber nicht sichtbar – man kann sich davon leicht überzeugen, indem man zum Beispiel fragt, an welchen Stellen im Faktor sf_lev die Partei "C" vorkommt beziehungsweise die Partei mit der Nummer 3:
sample_C <- which(sf_lev == "C")
sample_C
# [1] 4 8 11 16 20
sample_3 <- which(sf_lev == 3) # Syntax-Fehler:
sample_3
# integer(0)
Mit der Funktion which() wird untersucht, an welchen Stellen von sf_lev der Wert "C" angenommen wird; der Rückgabewert ist ein Vektor mit den entsprechenden Indizes (Zeile 2 und 3).
Sucht man stattdessen nach dem Level 3 (siehe Zeile 5), so erhält man einen Vektor der Länge null, da der Level 3 in sf_lev nicht vorkommt (er wird nur intern verwendet).
Der Unterschied zwischen einem ungeordneten und einem geordneten Faktor besteht im Sinne der Kodierung lediglich darin, dass jetzt andere Abfragen möglich sind, wie das folgende Beispiel zeigt; es wird der Faktor von oben als geordneter Faktor erzeugt:
# sample und lev wie oben
sf_ord <- factor(x = sample, levels = c("A", "B", "C", "D", "E"), ordered = TRUE)
sample_C <- which(sf_ord > "C")
sample_C
# [1] 3 7 10 15 19
Da der Faktor geordnet ist, kann man nach Parteien fragen, die größer sind als "C" (Zeile 4). Bei einem ungeordneten Faktor führt die Abfrage in Zeile 4 zu einem Syntax-Fehler (‘>’ not meaningful for factors
).
Mit der Lesart des Faktors als Kodierung eines Vektors, sollte auch klar sein, was passiert, wenn man versucht aus einem Vektor der Länge null einen Faktor zu bilden: Es ist erlaubt, keinen Vektor x aber dennoch Levels anzugeben, wenn ein Faktor erzeugt wird. Man kann sich dies als die Kodierung eines Vektors der Länge null vorstellen: jetzt wird nur die Zuordnung der Levels zu den Zahlen 1, 2,..., n hergestellt:
sf_0 <- factor(levels = c("A", "B", "C", "D", "E"))
sf_0
# factor(0)
# Levels: A B C D E
length(sf_0) # 0
mode(sf_0) # "numeric"
storage.mode(sf_0) # "integer"
Dar Faktor sf_0 wird ohne Stichprobe x erzeugt (Zeile 1), die 5 Levels werden aber gesetzt. Es entsteht ein Faktor der Länge null, der wie im Beispiel oben den Speichermodus integer besitzt – obwohl nichts zu speichern ist.
Die Funktion tabulate(): Abzählen, wie oft Zahlen in einem Vektor (oder Faktor) vorkommen
Die Wirkung der Funktion tabulate() wird besser verständlich, wenn man sich nochmal vergegenwärtigt, wie man beim Kodieren eines Vektors sample oder beim Bilden des Faktors zum Vektor sample vorgeht:
- man durchläuft die Komponenten des Vektors und bildet einen neuen "Vektor" fs der gleichen Länge,
- die erste Komponente sample1 ist zugleich der erste Level von fs, der intern als 1 abgespeichert wird: fs1 = 1,
- jede weitere Komponente, die mit sample1 übereinstimmt, wird ebenfalls als 1 abgespeichert,
- für jede neue Komponente in sample wird die nächste natürliche Zahl verwendet, um den Level abzuspeichern,
- die Komponenten des Vektors fs bestehen aus den Zahlen 1, 2,..., n, falls sample aus n verschiedenen Werten (Levels) besteht.
Und hat man diesen Vektor fs gebildet, ist es nicht mehr schwer, die Ausgabe zu erzeugen, die durch die Funktion table() gebildet wird: man muss nur noch abzählen, wie oft die Levels 1, 2,..., n im Vektor fs vorkommen.
In R gibt es die Funktion tabulate(), die den Großteil der hier beschriebenen Aufgaben übernimmt. Der Eingabewert bin für tabulate() ist entweder ein Vektor oder ein Faktor; Letzteres wird weiter unten beschrieben.
Falls bin ein Vektor ist, muss er aus positiven ganzen Zahlen bestehen; er entspricht dem Vektor fs oben. Der Eingabewert muss aber nicht genau die Gestalt eines Faktors haben, das heißt es müssen nicht alle Zahlen zwischen 1 und einem n vorkommen, es können auch Lücken enthalten sein.
Die Funktion tabulate() bildet dann einen Vektor der Länge max, wobei max der größte Wert im Eingabe-Vektor ist. Und die i-te Komponente im Rückgabe-Vektor gibt an, wie oft die Zahl i im Eingabe-Vektor vorkommt. Um dies an einem Beispiel zu demonstrieren:
x <- c(1, 1, 2, 3, 3, 4, 17)
t.x <- tabulate(bin = x)
storage.mode(t.x) # [1] "integer"
length(t.x) # 17
t.x
# [1] 2 1 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1
Zeile 1: Der Eingabe-Vektor x besteht aus 7 Komponenten; deren Werte liegen zwischen 1 und 17; die 1 und die 3 kommen doppelt vor, andere Zahlen einmal oder überhaupt nicht.
Zeile 2: Die Funktion tabulate() wird auf x angewendet und das Ergebnis in t.x abgespeichert.
Zeile 4 bis 7: t.x wird untersucht.
Zeile 4: Der Speichermodus ist "integer", es werden also keine Gleitkommazahlen sondern ausdrücklich ganze Zahlen in t.x verwendet.
Zeile 5: Die Länge von t.x ist gleich 17, was der größte Wert im Eingabe-Vektor ist.
Zeile 6 und 7: Die Ausgabe von t.x zeigt, dass für jeden ganzzahligen Wert von 1 bis 17 eine Komponente reserviert wurde und dass die i-te Komponente von t.x angibt, wie oft i in x vorkommt:
- Komponente: die 1 kommt zweimal vor,
- Komponente: die 2 kommt einmal vor,
- Komponente: die 3 kommt zweimal vor,
- Komponente: die 4 kommt einmal vor,
- bis 16. Komponente: 5 bis 16 kommen nicht vor,
- Komponente: die 17 kommt einmal vor.
Nullen und negative Zahlen im Eingabe-Vektor werden einfach ignoriert, wie das folgende Beispiel zeigt; der Vektor x von oben wird durch die drei führenden Komponenten (-1, -1, 0) ergänzt, die Ausgaben bleiben aber unverändert:
x <- c(-1, -1, 0, 1, 1, 2, 3, 3, 4, 17)
t.x <- tabulate(bin = x)
storage.mode(t.x) # [1] "integer"
length(t.x) # 17
t.x
# [1] 2 1 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1
Die Länge des Rückgabe-Vektors kann durch das zusätzliche Argument nbins gesetzt werden. Im folgenden Beispiel wird wieder der Eingabe-Vektor x aus dem ersten Beispiel verwendet, aber es wird zusätzlich das Argument xbins gesetzt:
x <- c(1, 1, 2, 3, 3, 4, 17)
t.x <- tabulate(bin = x, nbins = 20)
storage.mode(t.x) # [1] "integer"
length(t.x) # 20
t.x
# [1] 2 1 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
x <- c(1, 1, 2, 3, 3, 4, 17)
t.x <- tabulate(bin = x, nbins = 5)
storage.mode(t.x) # [1] "integer"
length(t.x) # 5
t.x
# [1] 2 1 2 1 0
Bisher wurde die Funktion tabulate() auf einen Vektor angewendet. Es ist auch möglich stattdessen einen Faktor einzugeben. Dazu wird wieder das Beispiel der Sonntagsfrage aufgegriffen; der dort definierte Faktor (Zeile 3) wird als Eingabewert bin für tabulate() verwendet (Zeile 8):
sample <- c("A", "A", "E", "C", "B", "A", "E", "C", "A", "E", "C", "B", "A", "B", "E", "C", "A", "B", "E", "C")
length(sample) # 20
sf <- factor(x = sample)
sf
# [1] A A E C B A E C A E C B A B E C A B E C
# Levels: A B C E
t.sf <- tabulate(bin = sf)
length(t.sf) # 4
t.sf
# [1] 6 4 5 5
table(sf)
# sf
# A B C E
# 6 4 5 5
Es entsteht ein Vektor der Länge 4 (also identisch mit der Anzahl der Levels des Faktors sf, siehe Zeile 6 und 10). Die Ausgabe zeigt (Zeile 11 und 12), wie oft die Levels im zugrundeliegenden Vektor sample vorkommen – und das sind zugleich die Werte, die die Funktion table() ausgibt (Zeile 17).
Die Attribute eines Faktors: levels und class
Abfrage der Levels
Mit der Funktion levels() können die Levels eines Faktors abgefragt werden (Zeile 4); die Anzahl der Levels eines Faktors kann mit der Funktion nlevels() bestimmt werden (Zeile 7). Eingabewert ist dabei jeweils der Faktor:
sample <- c("A", "A", "E", "C", "B", "A", "E", "C", "A", "E", "C", "B", "A", "B", "E", "C", "A", "B", "E", "C")
sf_ord <- factor(x = sample, levels = c("A", "B", "C", "D", "E"), ordered = TRUE)
levels(sf_ord)
# [1] "A" "B" "C" "D" "E"
nlevels(sf_ord) # 5
Veränderung der Levels
Hier werden 2 Möglichkeiten besprochen, wie man die Levels eines Faktors verändern kann:
- Umbenennen der Levels
- nicht vorkommende Levels entfernen.
Bisher wurde die Funktion levels() verwendet, um die Levels eines Faktors auszugeben. Man kann sie auch verwenden, um die Levels zu verändern.
Im folgenden Beispiel wird der geeignete Faktor zur Sonntagsfrage erzeugt. Anschließend werden die Levels umbenannt (anstelle von "A" wird "AP" für A-Partei gesetzt), siehe Zeile 7.
An der Ausgabe in den Zeilen 9 bis 11 sieht man, dass die Funktion levels() tatsächlich das Argument (hier sf_ord) verändert hat.
sample <- c("A", "A", "E", "C", "B", "A", "E", "C", "A", "E", "C", "B", "A", "B", "E", "C", "A", "B", "E", "C")
sf_ord <- factor(x = sample, levels = c("A", "B", "C", "D", "E"), ordered = TRUE)
sf_ord
# [1] A A E C B A E C A E C B A B E C A B E C
# Levels: A < B < C < D < E
levels(sf_ord) <- c("AP", "BP", "CP", "DP", "EP")
sf_ord
# [1] AP AP EP CP BP AP EP CP AP EP CP BP AP BP EP CP AP BP EP CP
# Levels: AP < BP < CP < DP < EP
Mit der Funktion droplevels() können diejenigen Levels aus einem Faktor entfernt werden, die in der zugrundeliegenden Stichprobe nicht vorkommen. Eingabewert der Funktion ist der Faktor. Der Rückgabewert der Funktion droplevels() ist wieder ein Faktor – nämlich der Faktor, der in all seinen Eigenschaften mit dem Eingabewert übereinstimmt, nur dass die unbesetzten Levels fehlen.
Das folgende Beispiel zeigt, wie bei der Sonntagsfrage die unbesetzten Levels entfernt werden:
sample <- c("A", "A", "E", "C", "B", "A", "E", "C", "A", "E", "C", "B", "A", "B", "E", "C", "A", "B", "E", "C")
sf_ord <- factor(x = sample, levels = c("A", "B", "C", "D", "E"), ordered = TRUE)
sf_ord
# [1] A A E C B A E C A E C B A B E C A B E C
# Levels: A < B < C < D < E
sf_ord <- droplevels(sf_ord)
sf_ord
# [1] A A E C B A E C A E C B A B E C A B E C
# Levels: A < B < C < E
Zeile 1 bis 5 zeigt nochmals die Definition des geordneten Faktors aus der Stichprobe. Neu ist Zeile 7: Auf der rechten Seite werden aus dem Faktor sf_ord die unbesetzten Levels entfernt (hier "D") und der entstehende Faktor wird sf_ord zugewiesen. Die Ausgabe von sf_ord zeigt (ab Zeile 8), dass der Faktor all seine Eigenschaften beibehalten hat, nur Level "D" fehlt.
Die Bedeutung der Klasse
Zu Beginn war von Klassen im Sinne einer Klassifizierung die Rede; jetzt wird Klasse im Sinne der objekt-orientierten Programmierung verwendet (siehe etwa Objekt-orientierte Programmiersprachen in Übersicht über Programmiersprachen).
Das Attribut class gibt die Klasse eines Objektes an und ist erst im Zusammenhang mit objekt-orientierter Programmierung verständlich. Da es bei Faktoren nur zwei Möglichkeiten für das Attribut class gibt, wird es hier kurz erklärt:
- Für einen ungeordneten Faktor hat das Attribut class den Wert
"factor"
. - Für einen geordneten Faktor hat das Attribut class den Wert
"ordered" "factor"
.
Dahinter verbirgt sich die Vererbung, ein wichtiges Konzept der objekt-orientierten Programmierung, das die Wiederverwendung von Quelltexten erlaubt und eine bessere Strukturierung von Objekten ermöglicht: Die Klasse "factor"
ist die Oberklasse, und jeder Faktor ist ein Objekt dieser Oberklasse. Ist ein Faktor ein spezieller, nämlich geordneter Faktor, ist er ein Objekt der Unterklasse "ordered"
.
Unterklasse heißt, dass alle Eigenschaften der Oberklasse übernommen werden und weitere Eigenschaften hinzukommen können (hier die Anordnung der Levels). Wäre allerdings die Klasse eines geordneten Faktors allein durch "ordered"
gegeben, könnte man die Oberklasse nicht erkennen. Daher wird als Klasse immer die eigentliche Klasse und die Vererbungs-Hierarchie der Oberklassen angegeben. Hat ein Objekt die Klasse "ordered" "factor"
, so ist dies so zu verstehen:
- das Objekt besitzt die Klasse
"ordered"
und "ordered"
ist Unterklasse von"factor"
.
Bei mehreren Zwischenstufen in der Vererbung, wird die Liste entsprechend länger.
Diagnose-Funktionen für Faktoren
Die Sprache R bietet eine Reihe von Diagnose-Funktionen, die schon für andere Datentypen besprochen wurden. Hier werden folgende Funktionen gezeigt:
- print()
- length()
- mode() und storage.mode()
- levels() und nlevels()
- str()
- class()
- summary()
- table().
Verwendet wird dazu wieder das Beispiel der Sonntagsfrage, bei dem ein ungeordneter Faktor mit 5 Levels erzeugt wird:
sample <- c("A", "A", "E", "C", "B", "A", "E", "C", "A", "E", "C", "B", "A", "B", "E", "C", "A", "B", "E", "C")
length(sample) # 20
sf_lev <- factor(x = sample, levels = c("A", "B", "C", "D", "E"))
Auf diesen Faktor werden nun die Diagnose-Funktionen angewendet:
# 1. print-Funktion
sf_lev
# [1] A A E C B A E C A E C B A B E C A B E C
# Levels: A B C D E
# 2. length()
length(sf_lev) # 20
# length(sf_lev) == length(sample)
# 3. mode() und storage.mode()
mode(sf_lev) # "numeric"
storage.mode(sf_lev) # "integer"
# Beachte: intern werden die Levels als ganze Zahlen abgespeichert, obwohl sie als Zeichen definiert wurden
# 4. levels() und nlevels()
levels(sf_lev)
# [1] "A" "B" "C" "D" "E"
nlevels(sf_lev)
# [1] 5
# 5. str()
str(sf_lev)
# Factor w/ 5 levels "A","B","C","D",..: 1 1 5 3 2 1 5 3 1 5 ...
# 6. class()
class(sf_lev)
# [1] "factor"
# sf_lev ist ungeordnet, bei einem geordneten Faktor erhält man:
# [1] "ordered" "factor"
# 7. summary()
summary(sf_lev)
# A B C D E
# 6 4 5 0 5
str(summary(sf_lev))
# Named int [1:5] 6 4 5 0 5
# - attr(*, "names")= chr [1:5] "A" "B" "C" "D" ...
# 8. table()
table(sf_lev)
# sf_lev
# A B C D E
# 6 4 5 0 5
Die Ausgabe von summary(sf_lev)
ist nicht eindeutig zu interpretieren: An der Ausgabe der Struktur erkennt man aber, dass ein numerischer Vektor mit den Häufigkeiten der Levels gebildet wird; die Bezeichnungen der Levels sind als Namen (Attribut names) an den Vektor weitergegeben.
Weitere Funktionen zum Erzeugen von Faktoren
as-dot-Funktionen
Im Abschnitt über Faktoren und geordnete Faktoren wurden die beiden Funktionen factor() und ordered() vorgestellt, die einen Vektor x in einen (geordneten) Faktor verwandeln; die Funktionen verfügen noch über weitere Argumente, die zum Großteil nicht besprochen wurden. Benötigt man sie in ihrer einfachsten Form (also wie in den ersten Beispielen zur Sonntagsfrage), kann der Vektor x auch direkt mit einer as-dot-Funktion in einen Faktor beziehungsweise einen geordneten Faktor verwandelt werden. Diese Operation ist für sehr große Vektoren interessant, da sie schneller ausgeführt wird als factor() beziehungsweise ordered().
Das folgende Skript zeigt zwei Beispiele:
sample <- c("A", "A", "E", "C", "B", "A", "E", "C", "A", "E", "C", "B", "A", "B", "E", "C", "A", "B", "E", "C")
sf <- as.factor(sample)
sf
# [1] A A E C B A E C A E C B A B E C A B E C
# Levels: A B C E
str(sf)
# Factor w/ 4 levels "A","B","C","E": 1 1 4 3 2 1 4 3 1 4 ...
sf.ord <- as.ordered(sample)
sf.ord
# [1] A A E C B A E C A E C B A B E C A B E C
# Levels: A < B < C < E
str(sf.ord)
# Ord.factor w/ 4 levels "A"<"B"<"C"<"E": 1 1 4 3 2 1 4 3 1 4 ...
Erzeugen von regelmäßigen Faktoren mit der Funktion gl()
Manchmal benötigt man – etwa zum Testen von Funktionen, die Stichproben auswerten – Faktoren mit einer regelmäßigen Anordnung der Komponenten. Mit regelmäßiger Anordnung der Komponenten ist gemeint, dass zum Beispiel alle Levels immer wieder der Reihe nach durchlaufen werden, oder jeder Level k-mal wiederholt wird, bevor der nächste Level folgt. Das folgende Beispiel zeigt diese regelmäßigen Anordnungen für das Beispiel der Sonntagsfrage:
A B C D E A B C D E A B C D E A B C D E
A A B B C C D D E E A A B B C C D D E E
A A A B B B C C C D D D E E E A A A B B
A A A A B B B B C C C C D D D D E E E E
Alle Folgen bestehen aus 20 Elementen. Im ersten Beispiel wird je ein Level angezeigt, im zweiten Beispiel wird jeder Level zweimal angezeigt und so weiter.
Erzeugt werden die zugehörigen Faktoren mit der Funktion gl() (gl steht als Abkürzung für generate factor levels). Sie besitzt folgende Eingabewerte:
- n: Die Anzahl der Levels (hier n = 5)
- k: Die Angabe, wie oft ein Level wiederholt werden soll (hier k = 1, 2, 3, 4)
- length: die Anzahl der Komponenten (hier 20)
- labels: ein Vektor der Länge n, der die Levels bezeichnet.
- ordered: die Angabe, ob der Faktor geordnet sein soll (default-Wert ist FALSE; in diesem Beispiel ist dies irrelevant).
Das folgende Skript erzeugt die Faktoren, die zu den oben gezeigten regelmäßigen Anordnungen der Levels gehören:
lev <- c("A", "B", "C", "D", "E")
sf1 <- gl(n = 5, k = 1, length = 20, labels = lev)
sf1
# [1] A B C D E A B C D E A B C D E A B C D E
# Levels: A B C D E
sf2 <- gl(n = 5, k = 2, length = 20, labels = lev)
sf2
# [1] A A B B C C D D E E A A B B C C D D E E
# Levels: A B C D E
sf3 <- gl(n = 5, k = 3, length = 20, labels = lev)
sf3
# [1] A A A B B B C C C D D D E E E A A A B B
# Levels: A B C D E
sf4 <- gl(n = 5, k = 4, length = 20, labels = lev)
sf4
# [1] A A A A B B B B C C C C D D D D E E E E
# Levels: A B C D E
Zeile 1: Die Bezeichnungen der Levels werden als Vektor abgespeichert.
Zeile 3: Da jeder der n = 5 Level nur einmal vorkommen soll, wird in gl() k = 1 gesetzt; insgesamt sollen 20 Komponenten erzeugt werden.
Zeile 8: Mit k = 2 erhält man zwei Wiederholungen und so weiter.
Zusammenfassung
Funktionen zum Erzeugen von Faktoren und geordneten Faktoren
Die folgende Tabelle zeigt eine Kurzbeschreibung der in diesem Kapitel vorgestellten Funktionen. Man beachte dabei aber, dass die gezeigten Argumente meist nicht die komplette Liste der Eingabewerte darstellt. Es werden immer nur diejenigen Eingabewerte gezeigt, die hier auch besprochen wurden. Für die allgemeine Verwendung der Funktionen ist es erforderlich die Dokumentation zu Rate zu ziehen.
Funktion | Beschreibung |
factor(x, levels, labels, ordered)
| Erzeugen eines Faktors aus einem Vektor x mit Levels levels, deren Bezeichnung labels und der Angabe, ob der Faktor geordnet ist |
ordered(x, ...)
| Erzeugen eines geordneten Faktors aus einem Vektor x und weiteren Argumenten wie bei factor() außer ordered |
is.factor(x)
| stellt fest, ob ein Objekt x ein Faktor ist |
is.ordered(x)
| stellt fest, ob ein Faktor x geordnet ist |
as.factor(x)
| Umwandeln von x in einen Faktor |
as.ordered(x)
| Umwandeln von x in einen geordneten Faktor |
gl(n, k, length, labels, ordered)
| erzeugt einen regelmäßigen Faktor mit n Levels und k Wiederholungen der Levels |
Die folgende Tabelle beschreibt die Rückgabewerte der Funktionen und deren Datentypen:
Funktion | Rückgabewert | Datentyp |
factor(x, levels, labels, ordered)
| Faktor mit derselben Länge wie x; die weiteren Eingabewerte sind optional und werden eventuell aus x erzeugt | class "factor"
oder class c("ordered", "factor")
, kurz: Faktor |
ordered(x, ...)
| geordneter Faktor mit derselben Länge wie x | class c("ordered", "factor")
, geordneter Faktor |
is.factor(x)
| TRUE oder FALSE, je nachdem ob x ein Faktor ist | "logical" |
is.ordered(x)
| TRUE oder FALSE, je nachdem ob x ein geordneter Faktor ist | "logical" |
as.factor(x)
| Umwandeln von x in einen Faktor | class "factor" |
as.ordered(x)
| Umwandeln von x in einen geordneten Faktor | class c("ordered", "factor")
|
gl(n, k, length, labels, ordered)
| regelmäßiger Faktor, der aus den Eingabewerten konstruiert wird (n Levels und k Wiederholungen der Levels) | Faktor |
Eigenschaften von (geordneten) Faktoren
Die folgende Tabelle zeigt eine Kurzbeschreibung der in diesem Kapitel vorgestellten Funktionen. Man beachte dabei aber, dass die gezeigten Argumente meist nicht die komplette Liste der Eingabewerte darstellt. Es werden immer nur diejenigen Eingabewerte gezeigt, die hier auch besprochen wurden. Für die allgemeine Verwendung der Funktionen ist es erforderlich die Dokumentation zu Rate zu ziehen.
Funktion | Beschreibung |
table(...)
| tabellarische Ausgabe eines oder mehrerer Faktoren: Bezeichnungen der Levels und ihre Häufigkeit im Faktor |
tabulate(bin, nbins)
| Feststellen, wie oft die Zahlen 1,..., max im Eingabe-Vektor vorkommen (max ist die größte, positive ganze Zahl im Eingabe-Vektor); nbins ist die Länge des erzeugten Vektors |
levels(x)
| Abfrage der Levels eines Faktors x |
levels(x) <- value
| Setzen der Levels eines Faktors x |
nlevels(x)
| Abfrage der Anzahl Levels eines Faktors x |
droplevels(x)
| Entfernen von unbesetzten Levels aus dem Faktor x |
str(object)
| Ausgabe der Struktur eines Objektes: in einer Zeile wird die wichtigste Information über den Faktor zusammengefasst |
summary(object)
| tabellarische Darstellung des Faktors wie durch table() |
Die folgende Tabelle beschreibt die Rückgabewerte der Funktionen und deren Datentypen:
Funktion | Rückgabewert | Datentyp |
table(...)
| Wurde bisher nur zur Ausgabe verwendet, die angezeigte Kontingenz-Tabelle ist von Klasse table, die weiterverarbeitet werden kann | Tabelle: class "table" |
tabulate(bin, nbins)
| Vektor vom Speichermodus "integer" der Länge max (größte, positive ganze Zahl im Eingabe-Vektor) beziehungsweise nbins; zählt, wie oft i = 1,...,max in bin vorkommt. | Vektor |
levels(x)
| Vektor mit Modus "character" und Länge gleich der Anzahl der Levels von x | "character"-Vektor |
levels(x) <- value
| kein Rückgabewert, dient zum Setzen der Levels des Faktors x | kein Rückgabewert (replacement form von levels()) |
nlevels(x)
| Anzahl Levels eines Faktors x | "integer" |
droplevels(x)
| Faktor, aus dem die unbesetzten Levels von x beseitigt wurden | Faktor |
str(object)
| Kein Rückgabewert, nur Ausgabe der Struktur eines Objektes. | "NULL": kein Rückgabewert |
summary(object)
| Vektor, dessen Komponenten die Häufigkeiten der Levels im Faktor sind, und dessen Attribut names die Bezeichnungen der Levels sind | Vektor (Modus "integer") der Länge des Faktors |