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"
BobLas 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 bobmano 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,
lapplygenera una lista; sin embargo, debido a las propiedades mágicas de R, el uso de[]en el segundo caso mantiene la clase data.frame delbobobjeto, eliminando así la necesidad de volver a convertir a data.frame usandoas.data.frameel argumentostringsAsFactors = FALSE.fuente
type.convertdespués de enviar todo acharacter, luegofactorsvolver a emitircharacternuevamente.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_ifse introdujo una nueva función :El ronroneo del paquete de RStudio ofrece otra alternativa:
fuente
purrrlínea devuelve una lista, no undata.frame!ivector decolnames().La opción global
puede ser algo que desee configurar
FALSEen 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
bobcdonde cada vector de factorbobfse 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
stringsAsFactorsconfiguración en algún lugar para ayudarlo (incluida una configuración global).fuente
bobpara 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
sapplyparte 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
transformpuede 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 = FALSEignorar todos los malentendidos.fuente
Si usaría el
data.tablepaquete 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
convertenhablarque da sintaxis legible compatible contidyversetuberías:que te da:
fuente
Con el
dplyruso de paquete cargadosi solo quieres cambiar la
phenotypecolumna 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