395 Stimmen

data.frame-Spalten von Faktoren in Zeichen umwandeln

Ich habe einen Datenrahmen. Nennen wir ihn bob :

> head(bob)
                 phenotype                         exclusion
GSM399350 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399351 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399352 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399353 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399354 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399355 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-

Ich möchte die Zeilen dieses Datenrahmens verketten (dies wird eine weitere Frage sein). Aber sehen Sie:

> class(bob$phenotype)
[1] "factor"

Bob Spalten sind Faktoren. Also, zum Beispiel

> as.character(head(bob))
[1] "c(3, 3, 3, 6, 6, 6)"       "c(3, 3, 3, 3, 3, 3)"      
[3] "c(29, 29, 29, 30, 30, 30)"

Ich verstehe das nicht ganz, aber ich vermute, dass es sich um Indizes für die Ebenen der Faktoren der Säulen (des Hofes von König Caractacus) von bob ? Nicht das, was ich brauche.

Seltsamerweise kann ich durch die Spalten von bob von Hand, und tun

bob$phenotype <- as.character(bob$phenotype)

was gut funktioniert. Und nach einiger Tipparbeit kann ich einen data.frame erhalten, dessen Spalten Zeichen und nicht Faktoren sind. Meine Frage lautet also: Wie kann ich dies automatisch tun? Wie kann ich einen data.frame mit Faktorenspalten in einen data.frame mit Zeichenspalten umwandeln, ohne jede Spalte manuell durchgehen zu müssen?

Zusatzfrage: Warum funktioniert der manuelle Ansatz?

387voto

Shane Punkte 95376

Ich folge nur Matt und Dirk. Wenn Sie Ihren bestehenden Datenrahmen neu erstellen möchten, ohne die globale Option zu ändern, können Sie ihn mit einer apply-Anweisung neu erstellen:

bob <- data.frame(lapply(bob, as.character), stringsAsFactors=FALSE)

Dies konvertiert alle Variablen in die Klasse "character", wenn Sie nur Faktoren konvertieren wollen, siehe Marek's Lösung unten .

Wie @hadley anmerkt, ist das Folgende prägnanter.

bob[] <- lapply(bob, as.character)

In beiden Fällen, lapply gibt eine Liste aus; aufgrund der magischen Eigenschaften von R ist jedoch die Verwendung von [] im zweiten Fall bleibt die data.frame-Klasse der bob Objekts, so dass eine Rückkonvertierung in ein data.frame nicht mehr erforderlich ist. as.data.frame mit dem Argument stringsAsFactors = FALSE .

341voto

Marek Punkte 47395

Nur Faktoren zu ersetzen:

i <- sapply(bob, is.factor)
bob[i] <- lapply(bob[i], as.character)

Im Paket dplyr in Version 0.5.0 neue Funktion mutate_if wurde eingeführt :

library(dplyr)
bob %>% mutate_if(is.factor, as.character) -> bob

...und wurde in Version 1.0.0 ersetzt durch across :

library(dplyr)
bob %>% mutate(across(where(is.factor), as.character)) -> bob

Paket purrr von RStudio bietet eine weitere Alternative:

library(purrr)
bob %>% modify_if(is.factor, as.character) -> bob

42voto

Dirk Eddelbuettel Punkte 345316

Die globale Option

stringsAsFactors: Die Standardeinstellung für Argumente von data.frame und read.table.

kann etwas sein, das Sie auf FALSE in Ihren Startdateien (z.B. ~/.Rprofile). Siehe bitte help(options) .

26voto

Kikapp Punkte 2053

Wenn Sie wissen, wie Faktoren gespeichert werden, können Sie die Verwendung von Funktionen, die auf der Anwendung basieren, zu diesem Zweck vermeiden. Das soll keineswegs heißen, dass die apply-Lösungen nicht gut funktionieren.

Die Faktoren sind als numerische Indizes strukturiert, die an eine Liste von "Ebenen" gebunden sind. Dies wird deutlich, wenn Sie einen Faktor in einen numerischen Wert umwandeln. So:

> fact <- as.factor(c("a","b","a","d")
> fact
[1] a b a d
Levels: a b d

> as.numeric(fact)
[1] 1 2 1 3

Die in der letzten Zeile zurückgegebenen Zahlen entsprechen den Niveaus des Faktors.

> levels(fact)
[1] "a" "b" "d"

Beachten Sie, dass levels() gibt ein Array von Zeichen zurück. Sie können diese Tatsache nutzen, um Faktoren einfach und kompakt in Strings oder numerische Werte umzuwandeln, z. B. so:

> fact_character <- levels(fact)[as.numeric(fact)]
> fact_character
[1] "a" "b" "a" "d"

Dies funktioniert auch für numerische Werte, vorausgesetzt, Sie verpacken Ihren Ausdruck in as.numeric() .

> num_fact <- factor(c(1,2,3,6,5,4))
> num_fact
[1] 1 2 3 6 5 4
Levels: 1 2 3 4 5 6
> num_num <- as.numeric(levels(num_fact)[as.numeric(num_fact)])
> num_num
[1] 1 2 3 6 5 4

22voto

scentoni Punkte 689

Wenn Sie einen neuen Datenrahmen wünschen bobc wobei jede Faktor-Vektor in bobf in einen Zeichenvektor umgewandelt wird, versuchen Sie dies:

bobc <- rapply(bobf, as.character, classes="factor", how="replace")

Wenn Sie sie dann wieder umwandeln wollen, können Sie einen logischen Vektor erstellen, der angibt, welche Spalten Faktoren sind, und diesen verwenden, um selektiv Faktor anzuwenden

f <- sapply(bobf, class) == "factor"
bobc[,f] <- lapply(bobc[,f], factor)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X