Wie Faktoren verketten, ohne dass sie auf ganzzahlige Ebene umgesetzt werden?
-
27-09-2019 - |
Frage
Ich war überrascht zu sehen, dass R Faktoren in eine Reihe zwingen, wenn Vektoren verketten. Dies geschieht auch, wenn die Pegel gleich sind. Zum Beispiel:
> facs <- as.factor(c("i", "want", "to", "be", "a", "factor", "not", "an", "integer"))
> facs
[1] i want to be a factor not an integer
Levels: a an be factor i integer not to want
> c(facs[1 : 3], facs[4 : 5])
[1] 5 9 8 3 1
, was die idiomatische Weise ist dies in R zu tun (in meinem Fall können diese Vektoren ziemlich groß sein)? Danke.
Lösung
Aus der R Mailingliste :
unlist(list(facs[1 : 3], facs[4 : 5]))
Um 'cbind' Faktoren, tun
data.frame(facs[1 : 3], facs[4 : 5])
Andere Tipps
Eine alternative Abhilfe ist, den Faktor zu konvertieren ein Zeichen Vektor zu sein, dann zurück zu konvertieren, wenn Sie verkettet werden finshed.
cfacs <- as.character(facs)
x <- c(cfacs[1:3], cfacs[4:5])
# Now choose between
factor(x)
# and
factor(x, levels = levels(facs))
Wow, ich hätte nie gedacht, es das tat. Hier ist eine Behelfslösung:
x <- c(facs[1 : 3], facs[4 : 5])
x <- factor(x, levels=1:nlevels(facs), labels=levels(facs))
x
Mit der Ausgabe:
[1] i want to be a
Levels: a an be factor i integer not to want
Es wird nur funktionieren, wenn die beiden Vektoren haben die gleichen Ebene wie hier.
Dies ist eine wirklich schlechte R Gotcha. Entlang dieser Linien, hier ist eine, die nur einige Stunden meiner Zeit verschlungen.
x <- factor(c("Yes","Yes","No", "No", "Yes", "No"))
y <- c("Yes", x)
> y
[1] "Yes" "2" "2" "1" "1" "2" "1"
> is.factor(y)
[1] FALSE
Es scheint mir die bessere Lösung ist Richies, die nötigen zum Charakter.
> y <- c("Yes", as.character(x))
> y
[1] "Yes" "Yes" "Yes" "No" "No" "Yes" "No"
> y <- as.factor(y)
> y
[1] Yes Yes Yes No No Yes No
Levels: No Yes
Solange Sie die Pegel richtig eingestellt erhalten, wie Richie erwähnt.
Da diese Frage gestellt wurde, Hadley Wickham ein forcats
Paket mit einer fct_c
Funktion entworfen für Probleme geschaffen hat, genau wie diese.
> library(forcats)
> facs <- as.factor(c("i", "want", "to", "be", "a", "factor", "not", "an",
"integer"))
> fct_c(facs[1:3], facs[4:5])
[1] i want to be a
Levels: a an be factor i integer not to want
Als Randbemerkung, fct_c
auch nicht durch Verkettungen von Faktoren lässt sich täuschen, die diskrepanten numerische Codierungen verwenden:
> x <- as.factor(c('c', 'z'))
> x
[1] c z
Levels: c z
> y <- as.factor(c('a', 'b', 'z'))
> y
[1] a b z
Levels: a b z
> c(x, y)
[1] 1 2 1 2 3
> fct_c(x, y)
[1] c z a b z
Levels: c z a b
> as.numeric(fct_c(x, y))
[1] 1 2 3 4 2
Basierend auf den anderen Antworten, die Zeichen verwenden Umwandlung ich die folgende Funktion zu verketten Faktoren bin mit:
concat.factor <- function(...){
as.factor(do.call(c, lapply(list(...), as.character)))
}
Diese Funktion können Sie verwenden, wie Sie c
verwenden würden.
Aus diesem Grunde ziehe ich an der Arbeit mit Faktoren innerhalb data.frames:
df <- data.frame(facs = as.factor(
c("i", "want", "to", "be", "a", "factor", "not", "an", "integer") ))
und Subset es mit Teilmenge () oder dplyr :: filter () usw. statt Zeilenindizes. Weil ich in diesem Fall sinnvolle Teilmengen Kriterien nicht habe, werde ich nur verwenden Kopf () und Schwanz ():
df1 <- head(df, 4)
df2 <- tail(df, 2)
Dann können Sie sie ganz einfach manipulieren, z.
dfc <- rbind(df1, df2)
dfc$facs
#[1] i want to be an integer
#Levels: a an be factor i integer not to want
Hier ist eine andere Art und Weise zu einem Faktor Variable hinzuzufügen, wenn das Setup etwas anders ist:
facs <- factor(1:3, levels=1:9,
labels=c("i", "want", "to", "be", "a", "factor", "not", "an", "integer"))
facs
# [1] i want to be a factor not an integer
# Levels: a an be factor i integer not to want
facs[4:6] <- levels(facs)[4:6]
facs
# [1] i want to be a factor
# Levels: i want to be a factor not an integer