Tengo un marco de datos. Vamos a llamarlo 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-
Me gustaría concatenar las filas de este marco de datos (esta será otra pregunta). Pero mira:
> class(bob$phenotype)
[1] "factor"
Bob
Las columnas son factores. Así por ejemplo:
> 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)"
No empiezo a entender esto, pero supongo que estos son índices de los niveles de los factores de las columnas (de la corte del rey caractaco) de bob
? No es lo que necesito.
Extrañamente puedo atravesar las columnas a bob
mano y hacer
bob$phenotype <- as.character(bob$phenotype)
que funciona bien Y, después de escribir un poco, puedo obtener un data.frame cuyas columnas son caracteres en lugar de factores. Entonces mi pregunta es: ¿cómo puedo hacer esto automáticamente? ¿Cómo convierto un data.frame con columnas de factor en un data.frame con columnas de caracteres sin tener que pasar manualmente por cada columna?
Pregunta adicional: ¿por qué funciona el enfoque manual?
bob
.Respuestas:
Solo siguiendo a Matt y Dirk. Si desea volver a crear su marco de datos existente sin cambiar la opción global, puede volver a crearlo con una instrucción de aplicación:
Esto convertirá todas las variables a la clase "personaje", si solo desea convertir factores, consulte la solución de Marek a continuación .
Como señala @hadley, lo siguiente es más conciso.
En ambos casos,
lapply
genera una lista; sin embargo, debido a las propiedades mágicas de R, el uso de[]
en el segundo caso mantiene la clase data.frame delbob
objeto, eliminando así la necesidad de volver a convertir a data.frame usandoas.data.frame
el argumentostringsAsFactors = FALSE
.fuente
type.convert
después de enviar todo acharacter
, luegofactors
volver a emitircharacter
nuevamente.bob[] <-
en el ejemplo obob <-
? el primero mantiene el data.frame; el segundo cambia el data.frame a una lista, dejando caer los nombres de las filas. Actualizaré la respuestairis[] <- lapply(iris, function(x) if (is.factor(x)) as.character(x) else {x})
Para reemplazar solo factores:
En el paquete dplyr en la versión 0.5.0
mutate_if
se introdujo una nueva función :El ronroneo del paquete de RStudio ofrece otra alternativa:
fuente
purrr
línea devuelve una lista, no undata.frame
!i
vector decolnames()
.La opción global
puede ser algo que desee configurar
FALSE
en sus archivos de inicio (por ejemplo, ~ / .Rprofile). Por favor mirahelp(options)
.fuente
Si comprende cómo se almacenan los factores, puede evitar el uso de funciones basadas en aplicar para lograr esto. Lo que no implica en absoluto que las soluciones de aplicación no funcionen bien.
Los factores se estructuran como índices numéricos vinculados a una lista de 'niveles'. Esto se puede ver si convierte un factor a numérico. Entonces:
Los números devueltos en la última línea corresponden a los niveles del factor.
Tenga en cuenta que
levels()
devuelve una matriz de caracteres. Puede usar este hecho para convertir factores de forma fácil y compacta a cadenas o números como este:Esto también funciona para valores numéricos, siempre que envuelva su expresión
as.numeric()
.fuente
as.character(f)
, es mejor tanto en legibilidad como en eficiencialevels(f)[as.numeric(f)]
. Si quisieras ser inteligente, podrías usarlolevels(f)[f]
en su lugar. Tenga en cuenta que al convertir un factor con valores numéricos, obtiene algún beneficio deas.numeric(levels(f))[f]
over, por ejemploas.numeric(as.character(f))
, pero esto se debe a que solo tiene que convertir los niveles a numéricos y luego a subconjuntos.as.character(f)
está bien como está.Si desea un nuevo marco de datos
bobc
donde cada vector de factorbobf
se convierta en un vector de caracteres, intente esto:Si luego desea volver a convertirlo, puede crear un vector lógico de las columnas que son factores, y usarlo para aplicar factor selectivamente
fuente
Normalmente hago esta función aparte de todos mis proyectos. Rapido y Facil.
fuente
Otra forma es convertirlo usando apply
Y uno mejor (el anterior es de clase 'matriz')
fuente
as.data.frame(lapply(...
Actualización: Aquí hay un ejemplo de algo que no funciona. Pensé que lo haría, pero creo que la opción stringsAsFactors solo funciona en cadenas de caracteres: deja solo los factores.
Prueba esto:
En términos generales, cada vez que tiene problemas con factores que deberían ser caracteres, hay una
stringsAsFactors
configuración en algún lugar para ayudarlo (incluida una configuración global).fuente
bob
para empezar (pero no después del hecho).O puedes probar
transform
:Solo asegúrese de poner todos los factores que desea convertir en caracteres.
O puedes hacer algo como esto y matar a todas las plagas de un solo golpe:
No es una buena idea meter los datos en un código como este, podría hacer el
sapply
parte por separado (en realidad, es mucho más fácil hacerlo así), pero entiendes el punto ... No he verificado el código, porque No estoy en casa, ¡así que espero que funcione! =)Este enfoque, sin embargo, tiene un inconveniente ... debe reorganizar las columnas después, mientras
transform
puede hacer lo que quiera, pero a costa de "escribir código de estilo peatonal" ...Entonces allí ... =)
fuente
Al comienzo de su marco de datos, incluya
stringsAsFactors = FALSE
ignorar todos los malentendidos.fuente
Si usaría el
data.table
paquete para las operaciones en data.frame, entonces el problema no está presente.Si ya tiene columnas de factor en su conjunto de datos y desea convertirlas en caracteres, puede hacer lo siguiente.
fuente
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 más fácil arreglar el DF y recrear el DT.Esto funciona para mí: finalmente pensé en un trazador de líneas
fuente
Esta función hace el truco
fuente
Tal vez una nueva opción?
fuente
Debe usar
convert
enhablar
que da sintaxis legible compatible contidyverse
tuberías:que te da:
fuente
Con el
dplyr
uso de paquete cargadosi solo quieres cambiar la
phenotype
columna específicamente.fuente
Esto funciona transformando todo a carácter y luego el numérico a numérico:
Adaptado de: Obtener tipos de columna de hoja de Excel automáticamente
fuente