11  OBJETOS Y ETIQUETAS ESPECIALES

En R existen algunos objetos con un valor determinado. Está, por ejemplo, la constante pi, es decir, la razón entre la circunferencia de un círculo y su diámetro:

pi
[1] 3.141593

También hay un vector con el nombre de los meses en inglés, tanto en su forma completa (month.name) como abreviada (month.abb):

month.abb
 [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"

Igualmente, hay vectores con las letras, tanto en minúscula (letters) como en mayúscula (LETTERS).

LETTERS
 [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S"
[20] "T" "U" "V" "W" "X" "Y" "Z"

Más allá de estas curiosidades, en R existen algunas cadenas de caracteres con significado y/o uso especial. Entre estas se encuentran Inf, -Inf, NaN, NA y NULL.

11.1 Infinito

Las etiquetas Inf y -Inf representan los conceptos de infinito positivo e infinito negativo, respectivamente. La primera se obtiene, por ejemplo, al evaluar la razón entre un real positivo y cero, mientras que la segunda se obtiene al evaluar la razón entre un real negativo y cero.

-5/0
[1] -Inf

Tanto Inf como -Inf son vectores numéricos y generan resultados consecuentes cuando se incorporan en una operación aritmética.

5 + Inf
[1] Inf

11.2 No es un número

La etiqueta NaN (not a number) aparece para expresar un resultado no numérico o indefinido. Paradójicamente, NaN es un vector numérico. Esto, sin embargo, tiene su razón de ser, que explicaremos en breve.

Si se evalúa, por ejemplo, el logaritmo de un real negativo o la razón Inf/Inf, el resultado es NaN.

log(-3)
Warning in log(-3): Se han producido NaNs
[1] NaN

Al ser NaN un vector numérico, admite operaciones aritméticas, sin generar mensajes de advertencia ni de error; no obstante, el resultado de cualquier operación que involucre un elemento NaN será, desde luego, NaN.

7 + NaN
[1] NaN

La función is.nan informa cuáles elementos dentro de un objeto son NaN.

a <- c(4, -Inf, NaN, Inf, -7.21)
is.nan(a)
[1] FALSE FALSE  TRUE FALSE FALSE

El vector a permite ilustrar la necesidad de que la etiqueta NaN sea de tipo numérico.

¿¡Cómo es eso de que los no números sí son numéricos?!

Teniendo en cuenta la restricción por atomicidad que tienen los vectores, en cuanto a que todos sus elementos tiene que ser del mismo tipo (cf. nota 8.1), la única forma de incorporar una etiqueta dentro de un vector numérico —sin alterar su naturaleza— es que dicha etiqueta también sea numérica.

is.numeric(a)
[1] TRUE

11.3 Información faltante

La información faltante se identifica en R con la etiqueta NA (not available).

Este descriptor no significa de manera alguna que el valor del elemento en cuestión sea cero; simplemente que no se tiene dicha información, ya sea porque se perdió o simplemente porque nunca se registró. El descriptor NA marca un espacio vacío.

Cuando se realiza un proceso de importación, R lee automáticamente los espacios vacíos como NA.

¡Los NA no son necesariamente NA!

Cuando se importan datos desde una fuente externa usando alguna de las funciones read.table, read.delim, read.delim2, read.csv o read.csv2 (cf. sección 6.1), los registros marcados con la cadena de caracteres NA —en mayúscula sostenida— se importan como NA.

Sin embargo, si la importación se realiza mediante la función read_excel{readxl}, este no es el comportamiento por defecto. Las celdas cuyo contenido fuera la cadena de caracteres NA, se importarían como la cadena de caracteres “NA”1; no, como el marcador NA.

Para los archivos Excel importados mediante read_excel{readxl}, basta con dejar vacías las celdas que se han de importar como NA.

Si se desea, también es posible indicar una cadena de caracteres personalizada que actúe como marcador de los NA. Para ello se usa el argumento na, con la cadena de caracteres entrecomillada como valor.

Supóngase, por ejemplo, que en una base de datos hay algunas observaciones con la etiqueta miss. Para que tales etiquetas se importen como NA, se usa la siguiente instrucción:

data <- readxl::read_excel("Libro1.xlsx", na = "miss")

El aspecto de la etiqueta NA es el mismo, sin importar el tipo del objeto contenedor. Consecuentemente, NA puede representar un número faltante, una cadena de caracteres faltante, un valor lógico faltante o un complejo faltante. Desde luego, dentro de los vectores —que son objetos atómicos—, NA representa un elemento faltante del correspondiente tipo.

La función is.na informa cuáles elementos dentro de un objeto son NA.

Considérese el siguiente vector:

v1 <- c(35, NA, 43, 18, NA, NA, 16)
is.na(v1)
[1] FALSE  TRUE FALSE FALSE  TRUE  TRUE FALSE

El vector de valores lógicos que se genera como resultado informa que el segundo, el quinto y el sexto elemento del vector v1 son NA.

Teniendo en cuenta que los valores lógivos TRUE equivalen a 1, mientras que los valores lógicos FALSE equivalen a 0 (cf. sección 10.5), es posible contabilizar el número de elementos faltantes sumando el anterior resultado:

sum(is.na(v1))
[1] 3

Para contabilizar el número de elementos no faltantes, se suma el resultado de la negación (!) de la función is.na.

sum(!is.na(v1))
[1] 4
¡Remueva los NA!

El resultado de cualquier operación que involucre al menos un NA es NA.

7 + NA
[1] NA
mean(c(5, 3, 8, 4, NA))
[1] NA

Este aspecto merece particular atención, por no corresponder con las expectativas que el usuario podría tener a partir de su experiencia con Excel, donde las operaciones que involucran celdas vacías (que son el equivalente de los NA) sí generan un resultado numérico.

Algunas funciones, tales como sum, mean, weighted.mean, var y sd permiten remover los NA, de manera que no participen en los cálculos. Para ello se usa el argumento na.rm = TRUE, que puede recordarse nemotécnicamente como remover los NA

Considérese nuevamente el vector v1:

v1 <- c(35, NA, 43, 18, NA, NA, 16)
sum(v1, na.rm = T)
[1] 112
mean(v1, na.rm = T)
[1] 28
sd(v1, na.rm = T)
[1] 13.14027

La función anyNA aplicada sobre un objeto permite averiguar, de manera rápida, si este tiene al menos un elemento perdido.

anyNA(v1)
[1] TRUE

11.4 El objeto nulo

NULL representa un objeto nulo o vacío. A diferencia de NA que se utiliza para representar posiciones faltantes dentro de un objeto y que se adapta a la clase del objeto contenedor, NULL no ocupa ninguna posición dentro de ningún objeto. NULL es en sí mismo un objeto único en su clase (clase NULL). El objeto NULL no tiene tamaño ni dimensiones.

is.vector(NULL)
[1] FALSE
class(NULL)
[1] "NULL"
length(NULL)
[1] 0

La función is.null permite evaluar si su argumento es el objeto nulo.

a <- NULL
is.null(a)
[1] TRUE

A pesar de la aparente intrascendentalidad del objeto nulo, este tiene una característica que resulta muy útil en programación: el objeto nulo existe.

a <- NULL
exists("a")
[1] TRUE

Cuando se realiza una asignación con el objeto nulo, se le da existencia a un ‘molde’ vacío y flexible que se adapta a la naturaleza de los elementos que se usen para su llenado. Esto hace que el objeto nulo sea muy útil para la inicialización de objetos.

Es común que en muchas funciones aparezcan argumentos con valor NULL. Se trata de argumentos que, sin ser obligatorios, podrían ser modificados por el usuario. En tales casos, el script suele incorporar la verificación sobre el estado de tales argumentos2, siguiendo diferentes líneas de acción dependiendo de si el objeto se mantiene nulo (no fue modificado por el usuario) o si se le asignó algún valor.

Para ilustrar lo anterior, supóngase que una función evalúa una serie de contrastes entre grupos de medias, acorde con una serie de coeficientes suministrados por el usuario. Dicha función podría incorporar un argumento optativo nombre.cont = NULL, que le permitiera al usuario personalizar el nombre de cada uno de los contrastes evaluados.

Si el usuario no le asignara ningún valor a dicho argumento, es decir, si is.null(nombre.cont) diera por resultado TRUE, la función podría crear nombres genéricos del tipo “Contraste 1”, “Contraste 2”, etc.


  1. Dando lugar a que el vector se adapte al tipo character.↩︎

  2. Usando la función is.null.↩︎