Was ein Faktor wirklich ist
Ein Faktor ist R's Antwort auf kategoriale Daten - Werte aus einer festen Auswahl von Möglichkeiten: Behandlungsgruppen, Umfrageantworten, T-Shirt-Größen. Ausgegeben sieht er wie ein Zeichenvektor aus, ist aber keiner. Intern ist ein Faktor ein Vektor aus Ganzzahlcodes plus eine Nachschlagetabelle mit Etiketten, den Levels:
Die Ausgabe zeigt die Etiketten, dann eine Levels:-Zeile mit der Auswahl. as.integer() legt die Mechanik offen: Die Codes kommen als 3 1 3 2 zurück, denn jeder Wert ist in Wahrheit ein Index in die Leveltabelle - und die Levels sortieren standardmäßig alphabetisch (large, medium, small), nicht in der Reihenfolge, in der die Daten ankamen. Also ist small Code 3 und large Code 1, was niemandes Intuition entspricht. Merk dir diese alphabetische Voreinstellung; sie treibt zwei der Fallen weiter unten an.
Warum überhaupt dieses zweischichtige Design statt schlichter Zeichenketten? Weil Statistik es braucht. Ein Modell kann "small" nicht mit einem Koeffizienten multiplizieren - aber es kann drei bekannte Levels als Spalten aus Nullen und Einsen dummy-codieren. Funktionen wie lm(), glm(), table() und die Maschinerie hinter der ANOVA stützen sich alle auf Faktoren, um zu wissen, dass eine Variable kategorial ist, wie die vollständige Menge der Kategorien lautet (einschließlich solcher, die in den Daten fehlen) und welche Kategorie die Baseline ist. Schlichte Zeichenvektoren tragen nichts davon.
Faktoren erzeugen: levels, labels und table()
Standardmäßig nimmt factor() die gefundenen unterschiedlichen Werte und sortiert sie alphabetisch zu Levels. Oft willst du sowohl die Menge als auch die Reihenfolge kontrollieren - übergib levels =:
Nun laufen die Levels in ihrer natürlichen Größenreihenfolge, und table() - die einzeilige Häufigkeitsauszählung, die du mit Faktoren ständig nutzen wirst - meldet die Anzahlen ebenfalls in dieser Reihenfolge. nlevels() zählt die Kategorien.
Zwei weitere Dinge bringt dir levels =. Werte in den Daten, die nicht in deiner Levelliste stehen, werden zu NA (gut: Tippfehler treten zutage, statt zu einer eigenen Kategorie zu werden). Und Levels ohne Vorkommen existieren trotzdem, sodass eine Zusammenfassung von Umfrageantworten "lehne stark ab: 0" zeigt, statt so zu tun, als hätte die Option nie existiert.
labels = benennt die Levels bei der Erzeugung um, was praktisch ist, wenn die Rohdaten Codes verwenden:
Und as.factor(x) ist der schnelle Umwandler für einen bestehenden Vektor, wenn die Voreinstellungen passen.
Geordnete Faktoren für ordinale Daten
Schlichte Faktoren behandeln Kategorien als ungeordnet - "rot" ist nicht kleiner als "blau". Aber manche kategorialen Skalen haben eine echte Rangfolge: niedrig/mittel/hoch, ablehnend/neutral/zustimmend. Erklär das mit ordered = TRUE:
Die Ausgabe zeigt nun Levels: low < medium < high, und Vergleichsoperatoren funktionieren: Du kannst fragen, ob eine Bewertung eine andere übersteigt, oder auf alles ab "medium" filtern - beides erzeugt bei einem ungeordneten Faktor Fehler (genauer: Warnungen und NAs). Geordnete Faktoren ändern außerdem, wie Modelle die Variable codieren (Polynomkontraste statt Dummy-Variablen), was bei ordinalen Prädiktoren meist erwünscht ist.
Nutze ordered = TRUE nur, wenn die Rangfolge real ist. Gewöhnliche Gruppen als geordnet zu codieren verändert die Modellausgabe auf leicht missverständliche Weise.
Die Referenzkategorie und relevel()
Das erste Level eines Faktors ist besonders: Modellfunktionen behandeln es als Referenzkategorie, die Baseline, an der der Koeffizient jedes anderen Levels gemessen wird. Da die Standard-Levelreihenfolge alphabetisch ist, wird deine Baseline vom Alphabet gewählt, sofern du nicht eingreifst - und dass "control" alphabetisch gegen "aspirin" verliert, ist keine wissenschaftliche Entscheidung.
relevel() befördert ein Level auf den ersten Platz:
Vorher: control steht nur durch alphabetisches Glück zufällig vorne. Nach relevel(..., ref = "control") steht es absichtlich vorne. In einer linearen Regression mit diesem Prädiktor beantwortet der treatment-Koeffizient nun "Wie unterscheidet sich treatment von control?" - die Frage, die du tatsächlich gestellt hast. Wann immer die kategorialen Koeffizienten eines Modells verwirrend aussehen, prüfe zuerst die Referenzkategorie.
(Für eine vollständige Umsortierung - nicht nur den ersten Platz - übergib factor() erneut einen kompletten levels =-Vektor.)
Die klassische Falle: einen Faktor in numeric umwandeln
Manchmal kommen Zahlen als Faktoren an - typischerweise eine CSV-Spalte, die einen verirrten nicht-numerischen Wert enthielt. Die Rückumwandlung sieht offensichtlich aus und geht denkwürdig schief:
as.numeric(f) gibt 2 1 3 zurück. Nicht 20, 10, 30 - die Level-Codes. Die Levels sortieren alphabetisch zu "10", "20", "30", also ist "20" Level 2 und wird zu ... 2. Kein Fehler, keine Warnung, plausibel aussehende kleine Ganzzahlen, die still deine Daten ersetzen. Analysen wurden deswegen zurückgezogen.
Der korrekte Weg führt über character: as.numeric(as.character(f)) holt zuerst die Etiketten als Text zurück und parst den Text dann als Zahlen - 20 10 30. Brenn dir dieses Idiom ein: Faktor zu numeric geht immer über as.character().
droplevels() und die stringsAsFactors-Geschichte
Das Teilmengenbilden eines Faktors behält die vollständige Levelmenge, selbst für Kategorien, die nicht mehr auftauchen:
Nach dem Herausfiltern von large meldet table() es weiterhin - mit Anzahl 0. Manchmal ist genau das richtig (du willst die leere Kategorie sichtbar haben). Wenn nicht - Gruppen mit Anzahl null überladen Diagramme und können stratifizierte Analysen brechen -, verwirft droplevels() Levels ohne Beobachtungen.
Eine historische Anmerkung, die du beim Lesen älteren Codes oder von Stack-Overflow-Antworten brauchst: Vor R 4.0 (2020) wandelten data.frame() und read.csv() jede Zeichenspalte automatisch in einen Faktor um - stringsAsFactors = TRUE war die Voreinstellung. Ein Jahrzehnt Tutorials ist übersät mit Behelfslösungen für Faktoren, die niemand wollte. Seit R 4.0 ist die Voreinstellung FALSE: Zeichenketten bleiben Zeichenketten, und du erzeugst Faktoren bewusst dort, wo eine Variable in deinem Data Frame wirklich kategorial ist. Das ist die richtige Gewohnheit - explizite Faktoren, absichtlich, mit Levels, die du gewählt hast.
Was du mitnimmst
- Ein Faktor = Ganzzahlcodes + Level-Etiketten; er sagt statistischen Funktionen, dass eine Variable kategorial ist.
- Steuere Kategorienmenge und -reihenfolge mit
levels =, benenne um mitlabels =, zähle mittable(). ordered = TRUEermöglicht Vergleiche für wirklich ordinale Skalen.- Das erste Level ist die Modell-Baseline - setz es bewusst mit
relevel(f, ref = ...). - Nie
as.numeric(f)direkt - immeras.numeric(as.character(f)). droplevels()räumt nach dem Teilmengenbilden ungenutzte Levels ab; seit R 4.0 bleiben Zeichenketten Zeichenketten, sofern du nicht selbst Faktoren erzeugst.
Als Nächstes: Data Frames - wo Faktoren, Zahlen und Text als Spalten einer Tabelle zusammenleben.
Häufig gestellte Fragen
Was ist ein Faktor in R?
Ein Faktor ist R's Typ für kategoriale Daten - Werte aus einer festen Menge von Möglichkeiten, den sogenannten Levels. Intern ist er ein Vektor aus Ganzzahlcodes plus eine Tabelle mit Level-Etiketten, was es statistischen Funktionen erlaubt, Kategorien korrekt zu behandeln (sie zu zählen, sie in Modellen dummy-zu-codieren), statt sie als freien Text zu sehen.
Wie wandelt man in R einen Faktor in numeric um?
Über character gehen: as.numeric(as.character(f)). as.numeric(f) direkt aufzurufen gibt die internen Level-Codes zurück (1, 2, 3, ...), nicht die Werte, die die Etiketten zeigen - ein Faktor, der "20" anzeigt, kann so als 2 zurückkommen. Das ist einer der häufigsten stillen Bugs in R.
Was macht relevel() in R?
Es verschiebt ein gewähltes Level an die erste Position: relevel(group, ref = "control"). Das erste Level ist die Referenzkategorie (Baseline), mit der Modellfunktionen wie lm() und glm() jedes andere Level vergleichen - es bewusst zu wählen sorgt dafür, dass Regressionskoeffizienten das bedeuten, was du beabsichtigst.
Warum zeigt mein Faktor noch Levels, die ich entfernt habe?
Das Teilmengenbilden eines Faktors behält die vollständige Levelmenge, auch wenn manche Levels nicht mehr vorkommen, sodass table() Kategorien mit Anzahl null zeigt und Modelle weiterhin Platz für sie reservieren. Führ droplevels() auf der Teilmenge aus, um die ungenutzten Levels zu verwerfen.