Numeric e integer: los dos tipos numéricos de R
R almacena los números de dos maneras. Numeric (almacenado como coma flotante de doble precisión) es el tipo por defecto - cada número que escribes es un double a menos que digas lo contrario. Integer es un tipo separado de entero exacto que pides con el sufijo L:
En la práctica rara vez necesitas preocuparte: R convierte entre ellos en silencio, y is.numeric() es TRUE para ambos (mira tipos de datos para el sistema de tipos completo). El único lugar donde la distinción se nota es la división - / siempre devuelve un double, incluso entre dos integers:
Los integers aparecen sobre todo como salida de funciones de conteo (length(), seq_len(), nrow()) y como valores de índice. Cuando necesites división de números enteros, R tiene un operador dedicado - cubierto más abajo.
La familia de redondeo
R te da cinco formas de recortar un número, cada una con un significado distinto:
round(x, digits)- a un número de decimales (por defecto 0).floor(x)- hacia abajo al entero más cercano, siempre hacia el infinito negativo.ceiling(x)- hacia arriba, siempre hacia el infinito positivo.trunc(x)- corta los decimales, siempre hacia cero. Fíjate en la diferencia con los negativos:trunc(-2.7)es-2, perofloor(-2.7)es-3.signif(x, digits)- a un número de cifras significativas, no de decimales:signif(123456, 2)es120000.
Y una sorpresa famosa: round() usa el redondeo al par más cercano (redondeo bancario) en las mitades exactas, según el estándar IEEE 754:
Eso imprime 0 2 2 4 - cada mitad se redondea al número par más cercano. No es un bug; evita un sesgo sistemático al alza cuando sumas muchos valores redondeados. Si un informe necesita el redondeo de la escuela, añade un pequeño empujón o formatea en la capa de presentación.
Funciones matemáticas del día a día
Lo básico funciona exactamente como imaginas:
sqrt() es la raíz cuadrada, abs() el valor absoluto, ^ es la potenciación, y exp(x) es e elevado a x - así que exp(1) es el número de Euler, aproximadamente 2.718282.
La función que hace tropezar a la gente es log(). En R, log() es el logaritmo natural (base e), no base 10:
La primera línea imprime aproximadamente 4.60517 - no el 2 que espera un lector de base 10. Recurre a log10() y log2() cuando quieras esas bases, o pasa base = explícitamente. (Esta convención es estándar en estadística, donde el logaritmo natural es el predeterminado.)
Módulo %% y división entera %/%
Dos operadores cubren la aritmética de restos:
%% es el módulo (resto): 17 dividido entre 5 es 3 con resto 2. %/% es la división entera: cuántos 5 completos caben en 17. Juntos satisfacen x == (x %/% y) * y + (x %% y).
El uso clásico de %% es comprobar la divisibilidad:
Una sutileza con los números negativos: el %% de R toma el signo del divisor (como Python, a diferencia de C):
Eso es 2, no -1 - R responde a "¿qué le sumo a un múltiplo de 3 para llegar a -7?", lo que mantiene los resultados en 0..2 para un divisor positivo. Práctico para envolver índices; sorprendente si vienes de C o Java.
Valores especiales: Inf, -Inf y NaN
Los números de R siguen IEEE 754, así que algunas operaciones producen valores especiales en lugar de errores:
1/0 es Inf (infinito), -1/0 es -Inf, y 0/0 - una cantidad genuinamente indefinida - es NaN, "not a number". La distinción importa: Inf es una respuesta ("más grande que cualquier cosa"), NaN es la ausencia de una. Los compruebas con funciones dedicadas, porque == NaN nunca funciona:
Fíjate en la última línea: NaN también cuenta como NA, así que is.na() lo captura - una razón más por la que is.na() es la comprobación estándar de "¿es este valor inutilizable?" (más en valores ausentes).
R también lee y escribe notación científica de forma nativa - 2.5e3 es 2500, y los números muy pequeños o muy grandes se imprimen en notación e por defecto:
Usa format(x, scientific = FALSE) (o la opción scipen) cuando un informe necesite decimales normales.
La sorpresa de la coma flotante
Todos los lenguajes que almacenan decimales en binario comparten esta, y R no es la excepción:
FALSE - porque 0.1 + 0.2 es en realidad 0.30000000000000004. Ni 0.1 ni 0.2 tienen representación binaria exacta, y los pequeños errores se acumulan. La impresión por defecto de R lo oculta mostrando 7 dígitos significativos, por eso el problema parece invisible hasta que falla una comparación con ==.
La regla: nunca compares decimales calculados con ==. Usa all.equal(), que compara dentro de una tolerancia sensata:
Envuélvelo en isTRUE() porque all.equal() devuelve una descripción de la diferencia (no FALSE) cuando los valores difieren. Para trabajo con enteros donde la exactitud importa, los integers son exactos hasta unos 2.100 millones - otra razón por la que el código de conteo usa el tipo integer.
Lo que te llevas
- Cada número que escribes es un double;
42Lcrea un integer, y/devuelve un double en cualquier caso. round()redondea las mitades al par;floor/ceiling/trunc/signifrecortan cada uno de forma distinta - sabe cuál quieres decir.log()es el logaritmo natural; usalog10(),log2()obase =para otras bases.%%da el resto (el signo sigue al divisor),%/%el cociente entero.1/0esInf,0/0esNaN, y0.1 + 0.2 != 0.3- compara decimales conall.equal(), nunca con==.
Lo siguiente: la otra mitad de los datos cotidianos - las cadenas, y las funciones que R te da para construirlas, formatearlas y buscar en ellas.
Preguntas frecuentes
¿Cuál es la diferencia entre numeric e integer en R?
Numeric (double) es el tipo por defecto de R para cualquier número que escribas - 42 es un double aunque parezca entero. Integer es un tipo de almacenamiento separado que pides con un sufijo L: 42L. La división normal siempre devuelve un double, incluso entre integers; usa %/% para la división entera.
¿log() en R es el logaritmo natural?
Sí - log(x) en R es el logaritmo natural (base e), no base 10. Usa log10() para base 10, log2() para base 2, o log(x, base = b) para cualquier base. log(100) es aproximadamente 4.605, no 2.
¿Cómo funciona round() en R?
round(x, digits) redondea al número dado de decimales, pero las mitades exactas usan "redondeo al par más cercano" (redondeo bancario): round(2.5) es 2 y round(3.5) es 4. Esto sigue el estándar IEEE 754 y reduce el sesgo al sumar valores redondeados, pero sorprende a quien espera el redondeo de la escuela.
¿Por qué 0.1 + 0.2 no es igual a 0.3 en R?
Los doubles se almacenan en binario, y 0.1, 0.2 y 0.3 no tienen representación binaria exacta, así que 0.1 + 0.2 es en realidad 0.30000000000000004. Nunca compares decimales calculados con ==; usa isTRUE(all.equal(x, y)) o comprueba abs(x - y) < 1e-9.