Deberías usar factores. Sí, pueden ser una molestia, pero mi teoría es que el 90% de por qué son una molestia se debe a que en read.table
y read.csv
, el argumento stringsAsFactors = TRUE
por defecto (y la mayoría de los usuarios pierden esta sutileza). Digo que son útiles porque los paquetes de ajuste de modelos como lme4 usan factores y factores ordenados para ajustar de manera diferencial los modelos y determinar el tipo de contrastes a utilizar. Y los paquetes de gráficos también los usan para agrupar. ggplot
y la mayoría de las funciones de ajuste de modelos coaccionan vectores de caracteres a factores, por lo que el resultado es el mismo. Sin embargo, terminas con advertencias en tu código:
lm(Petal.Length ~ -1 + Species, data=iris)
# Call:
# lm(formula = Petal.Length ~ -1 + Species, data = iris)
# Coefficients:
# Speciessetosa Speciesversicolor Speciesvirginica
# 1.462 4.260 5.552
iris.alt <- iris
iris.alt$Species <- as.character(iris.alt$Species)
lm(Petal.Length ~ -1 + Species, data=iris.alt)
# Call:
# lm(formula = Petal.Length ~ -1 + Species, data = iris.alt)
# Coefficients:
# Speciessetosa Speciesversicolor Speciesvirginica
# 1.462 4.260 5.552
Mensaje de advertencia: En model.matrix.default(mt, mf, contrasts)
:
variable Species
convertida afactor
Una cosa complicada es todo drop=TRUE
. En vectores, esto funciona bien para eliminar niveles de factores que no están en los datos. Por ejemplo:
s <- iris$Species
s[s == 'setosa', drop=TRUE]
# [1] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [11] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [21] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [31] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [41] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# Levels: setosa
s[s == 'setosa', drop=FALSE]
# [1] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [11] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [21] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [31] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [41] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# Levels: setosa versicolor virginica
Sin embargo , con data.frame
s, el comportamiento de [.data.frame()
es diferente: vea este correo electrónico o ?"[.data.frame"
. Usar drop=TRUE
en data.frame
s no funciona como te imaginas:
x <- subset(iris, Species == 'setosa', drop=TRUE) # susbetting with [ behaves the same way
x$Species
# [1] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [11] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [21] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [31] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# [41] setosa setosa setosa setosa setosa setosa setosa setosa setosa setosa
# Levels: setosa versicolor virginica
Afortunadamente, puede eliminar factores fácilmente droplevels()
para eliminar los niveles de factor no utilizados para un factor individual o para cada factor en a data.frame
(desde R 2.12):
x <- subset(iris, Species == 'setosa')
levels(x$Species)
# [1] "setosa" "versicolor" "virginica"
x <- droplevels(x)
levels(x$Species)
# [1] "setosa"
Así es como evitar que los niveles seleccionados entren en ggplot
leyendas.
Internamente, factor
s son números enteros con un vector de caracteres de nivel de atributo (ver attributes(iris$Species)
y class(attributes(iris$Species)$levels)
), que es limpio. Si tuviera que cambiar el nombre de un nivel (y estuviera usando cadenas de caracteres), esta sería una operación mucho menos eficiente. Y cambio mucho los nombres de los niveles, especialmente para las ggplot
leyendas. Si falsifica factores con vectores de caracteres, existe el riesgo de que cambie solo un elemento y cree accidentalmente un nuevo nivel separado.