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 andere Frage sein). Aber schau:
> class(bob$phenotype)
[1] "factor"
Bob
Die 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 fange nicht an, das zu verstehen, aber ich denke, dies sind Indizes für die Faktoren der Säulen (des Hofes des Königs Caractacus) von bob
? Nicht was ich brauche.
Seltsamerweise kann ich die Säulen bob
von Hand durchgehen und es tun
bob$phenotype <- as.character(bob$phenotype)
das funktioniert gut. Und nach einigem Tippen kann ich einen data.frame erhalten, dessen Spalten eher Zeichen als Faktoren sind. Meine Frage lautet also: Wie kann ich das automatisch tun? Wie konvertiere ich einen data.frame mit Faktorspalten in einen data.frame mit Zeichenspalten, ohne jede Spalte manuell durchgehen zu müssen?
Bonusfrage: Warum funktioniert der manuelle Ansatz?
bob
.Antworten:
Ich folge nur Matt und Dirk. Wenn Sie Ihren vorhandenen Datenrahmen neu erstellen möchten, ohne die globale Option zu ändern, können Sie ihn mit einer apply-Anweisung neu erstellen:
Dadurch werden alle Variablen in die Klasse "Zeichen" konvertiert. Wenn Sie nur Faktoren konvertieren möchten, siehe Mareks Lösung unten .
Wie @hadley hervorhebt, ist das Folgende prägnanter.
In beiden Fällen wird
lapply
eine Liste ausgegeben.[]
Aufgrund der magischen Eigenschaften von R behält die Verwendung von im zweiten Fall jedoch die data.frame-Klasse desbob
Objekts bei, wodurch die Notwendigkeit entfällt,as.data.frame
mit dem Argument zurück in einen data.frame zu konvertierenstringsAsFactors = FALSE
.quelle
type.convert
nachdem alles Gießencharacter
, dann Neufassungfactors
zurück zucharacter
wieder.bob[] <-
im Beispiel verwendet oderbob <-
?; der erste behält den data.frame; Der zweite ändert den data.frame in eine Liste und löscht die Rownamen. Ich werde die Antwort aktualisiereniris[] <- lapply(iris, function(x) if (is.factor(x)) as.character(x) else {x})
Um nur Faktoren zu ersetzen:
Im Paket dplyr in Version 0.5.0 wurde eine neue Funktion
mutate_if
eingeführt :Das Paket purrr von RStudio bietet eine weitere Alternative:
quelle
purrr
Zeile gibt eine Liste zurück, keinedata.frame
!i
einen Vektor von habencolnames()
.Die globale Option
Möglicherweise möchten Sie dies
FALSE
in Ihren Startdateien festlegen (z. B. ~ / .Rprofile). Bitte sehen Siehelp(options)
.quelle
Wenn Sie verstehen, wie Faktoren gespeichert werden, können Sie vermeiden, anwendungsbasierte Funktionen zu verwenden, um dies zu erreichen. Was keineswegs bedeutet, dass die Anwendungslösungen nicht gut funktionieren.
Faktoren sind als numerische Indizes strukturiert, die an eine Liste von „Ebenen“ gebunden sind. Dies wird angezeigt, wenn Sie einen Faktor in einen numerischen Wert umwandeln. Damit:
Die in der letzten Zeile zurückgegebenen Zahlen entsprechen den Pegeln des Faktors.
Beachten Sie, dass
levels()
ein Array von Zeichen zurückgegeben wird. Mit dieser Tatsache können Sie Faktoren einfach und kompakt in Zeichenfolgen oder Zahlen wie diese umwandeln:Dies funktioniert auch für numerische Werte, sofern Sie Ihren Ausdruck einschließen
as.numeric()
.quelle
as.character(f)
ist sowohl in der Lesbarkeit als auch in der Effizienz besser zulevels(f)[as.numeric(f)]
. Wenn Sie klug sein wollen, können Sielevels(f)[f]
stattdessen verwenden. Beachten Sie, dass Sie beim Konvertieren eines Faktors mit numerischen Werten einige Vorteileas.numeric(levels(f))[f]
erzielen, z. B.as.numeric(as.character(f))
weil Sie nur die Ebenen in numerische Werte und dann in Teilmengen konvertieren müssen.as.character(f)
ist gut so wie es ist.Wenn Sie einen neuen Datenrahmen wünschen,
bobc
in dem jeder Faktorvektor inbobf
einen Zeichenvektor konvertiert wird, versuchen Sie Folgendes:Wenn Sie es dann zurückkonvertieren möchten, können Sie einen logischen Vektor erstellen, dessen Spalten Faktoren sind, und diesen verwenden, um den Faktor selektiv anzuwenden
quelle
Normalerweise mache ich diese Funktion von all meinen Projekten getrennt. Schnell und einfach.
quelle
Eine andere Möglichkeit besteht darin, es mit apply zu konvertieren
Und eine bessere (die vorherige ist von der Klasse 'Matrix')
quelle
as.data.frame(lapply(...
Update: Hier ist ein Beispiel für etwas, das nicht funktioniert. Ich dachte, es würde, aber ich denke, dass die Option stringsAsFactors nur für Zeichenfolgen funktioniert - sie lässt die Faktoren in Ruhe.
Versuche dies:
Wenn Sie Probleme mit Faktoren haben, die Zeichen sein sollten, gibt es im Allgemeinen eine
stringsAsFactors
Einstellung, die Ihnen helfen kann (einschließlich einer globalen Einstellung).quelle
bob
(aber nicht nachträglich).Oder Sie können versuchen
transform
:Stellen Sie einfach sicher, dass Sie jeden Faktor, den Sie konvertieren möchten, in Zeichen umwandeln.
Oder Sie können so etwas tun und alle Schädlinge mit einem Schlag töten:
Es ist keine gute Idee, die Daten in Code wie diesen zu verschieben, ich könnte das tun
sapply
Teil separat (eigentlich ist es viel einfacher, dies so zu tun), aber Sie verstehen, dass ... ich den Code nicht überprüft habe, weil Ich bin nicht zu Hause, also hoffe ich, dass es funktioniert! =)Dieser Ansatz hat jedoch einen Nachteil ... Sie müssen die Spalten anschließend neu organisieren, während
transform
Sie mit dem tun können, was Sie möchten , jedoch auf Kosten des "Code-Schreibens im Fußgängerstil" ...Also da ... =)
quelle
Zu Beginn Ihres Datenrahmens schließen Sie ein
stringsAsFactors = FALSE
, um alle Missverständnisse zu ignorieren.quelle
Wenn Sie
data.table
package für die Operationen an data.frame verwenden würden, liegt das Problem nicht vor.Wenn Ihr Datensatz bereits eine Faktorspalte enthält und Sie diese in Zeichen konvertieren möchten, können Sie Folgendes tun.
quelle
In [<-.data.table(*tmp*, sapply(bob, is.factor), : Coerced 'character' RHS to 'double' to match the column's type. Either change the target column to 'character' first (by creating a new 'character' vector length 1234 (nrows of entire table) and assign that; i.e. 'replace' column), or coerce RHS to 'double' (e.g. 1L, NA_[real|integer]_, as.*, etc) to make your intent clear and for speed. Or, set the column type correctly up front when you create the table and stick to it, please.
Es ist einfacher, den DF zu reparieren und den DT neu zu erstellen.Das funktioniert bei mir - ich habe mir endlich einen Einzeiler ausgedacht
quelle
Diese Funktion macht den Trick
quelle
Vielleicht eine neuere Option?
quelle
Sie sollten verwenden
convert
inhablar
mit kompatibeler lesbarer Syntax gibt , dietidyverse
: Rohrewas dir gibt:
quelle
Mit dem
dplyr
geladenen Paket verwendenwenn Sie nur die
phenotype
-column speziell ändern möchten.quelle
Dies funktioniert, indem alle in Zeichen und dann die Zahlen in Zahlen umgewandelt werden:
Angepasst von: Holen Sie sich automatisch Spaltentypen von Excel-Tabellen
quelle