2016-08-24 3 views
6

Ich möchte <NA> Werte in einer Faktoren-Spalte mit einem gültigen Wert ersetzen. Aber ich kann keinen Weg finden. Dieses Beispiel dient nur zur Demonstration. Die ursprünglichen Daten stammen aus einer fremden CSV-Datei, mit der ich mich befassen muss.ersetzen <NA> in einer Faktor-Spalte in R

df <- data.frame(a=sample(0:10, size=10, replace=TRUE), 
       b=sample(20:30, size=10, replace=TRUE)) 
df[df$a==0,'a'] <- NA 
df$a <- as.factor(df$a) 

könnte wie folgt aussehen

 a b 
1  1 29 
2  2 23 
3  3 23 
4  3 22 
5  4 28 
6 <NA> 24 
7  2 21 
8  4 25 
9 <NA> 29 
10 3 24 

Jetzt möchte ich die <NA> Werte mit einer Nummer ersetzen.

df[is.na(df$a), 'a'] <- 88 
In `[<-.factor`(`*tmp*`, iseq, value = c(88, 88)) : 
    invalid factor level, NA generated 

Ich glaube, ich habe ein grundlegendes R-Konzept über Faktoren verpasst. Bin ich? Ich kann nicht verstehen, warum es nicht funktioniert. Ich denke, invalid factor level bedeutet, dass 88 ist keine gültige Ebene in diesem Faktor, richtig? Also muss ich der Faktorspalte sagen, dass es eine andere Ebene gibt?

+0

Ich verstehe nicht, warum Sie die Zeile des Codes haben, df $ a <- as.factor (df $ a), warum willst du das c Alter als Faktoren? – user1945827

+1

@buhtz: Wenn man nicht einen Wert von '0' im 'data.frame' Aufruf ausprobiert, kann man das Problem nicht replizieren, vielleicht besser zu 'set.seed()'. – 000andy8484

+0

@ 000andy8484 Danke für diesen Hinweis. Ich werde das nächste Mal an meine Notizen anheften. – buhtz

Antwort

13

1) addNAfac Wenn ein Faktor addNA(fac) ist der gleiche, aber mit Faktor NA als Ebene hinzugefügt.Siehe ?addNA

Um die NA Ebene zu zwingen, 88 zu sein:

facna <- addNA(fac) 
levels(facna) <- c(levels(fac), 88) 

geben:

> facna 
[1] 1 2 3 3 4 88 2 4 88 3 
Levels: 1 2 3 4 88 

1a) Dies in einer einzigen Zeile geschrieben werden kann wie folgt:

`levels<-`(addNA(fac), c(levels(fac), 88)) 

2) Faktor Es kann auch in einer Linie mit den verschiedenen Argumente von factor wie folgt geschehen:

factor(fac, levels = levels(addNA(fac)), labels = c(levels(fac), 88), exclude = NULL) 

2a) oder äquivalent:

factor(fac, levels = c(levels(fac), NA), labels = c(levels(fac), 88), exclude = NULL) 

3) ifelse Ein weiterer Ansatz ist:

factor(ifelse(is.na(fac), 88, paste(fac)), levels = c(levels(fac), 88)) 

Hinweis: Wir verwendeten die folgenden eingabe fac

fac <- structure(c(1L, 2L, 3L, 3L, 4L, NA, 2L, 4L, NA, 3L), .Label = c("1", 
"2", "3", "4"), class = "factor") 

Update: verbessert haben (1) und addiert (1a).

+0

Danke für diese erstaunlich umfassende Lösung! Ihre ifelse Lösung war die erste für mich, die für viele Spalten gleichzeitig arbeiten konnte! – surelyourejoking

2

Das Grundkonzept einer Faktorvariablen ist, dass sie nur bestimmte Werte annehmen kann, d. H. Die levels. Ein Wert nicht in levels ist ungültig.

Sie haben zwei Möglichkeiten:

Wenn Sie eine Variable haben, die dieses Konzept folgt, stellen Sie sicher, dass alle Ebenen definieren, wenn Sie es schaffen, auch solche ohne Werte entsprechen.

Oder machen Sie die Variable eine Zeichenvariable und damit arbeiten.

PS: Diese Probleme ergeben sich oft aus dem Datenimport. Zum Beispiel sieht es so aus, als ob es eine numerische Variable und keine Faktorvariable sein sollte.

+0

Es ist vom Datenimport, du hast Recht. – buhtz

+0

Es ist schwer zu entscheiden, wo die grüne Markierung hier steht! ;) Ihre Antwort lieferte mir die Hintergrundinformationen über das Grundkonzept, das ich vorher vermisste. Vielen Dank. – buhtz

2

Das Problem ist, dass NA ist kein Niveau dieses Faktors:

> levels(df$a) 
[1] "2" "4" "5" "9" "10" 

Sie können es nicht sofort ändern, aber die folgenden den Trick:

df$a <- as.numeric(as.character(df$a)) 
df[is.na(df$a),1] <- 88 
df$a <- as.factor(df$a) 
> df$a 
[1] 9 88 3 9 5 9 88 8 3 9 
Levels: 3 5 8 9 88 
> levels(df$a) 
[1] "3" "5" "8" "9" "88" 
+0

'df $ a <- as.numerisch (levels (df $ a)) [df $ a]' ist eine etwas effizientere Variante für 'as.numeric (as.character())'. – 000andy8484

0

andere Art und Weise zu tun ist:

#check levels 
levels(df$a) 
#[1] "3" "4" "7" "9" "10" 

#add new factor level. i.e 88 in our example 
df$a = factor(df$a, levels=c(levels(df$a), 88)) 

#convert all NA's to 88 
df$a[is.na(df$a)] = 88 

#check levels again 
levels(df$a) 
#[1] "3" "4" "7" "9" "10" "88"