Los operadores que te da R
Los operadores de R se agrupan en cuatro familias de trabajo: aritméticos (+ - * / ^ %% %/%), de comparación (== != < <= > >=), lógicos (& | && || ! xor) y la comprobación de pertenencia %in%. Dos cosas los diferencian de la mayoría de lenguajes: casi todos están vectorizados - operan sobre vectores enteros de una vez, elemento a elemento - y R tiene dos operadores AND y dos operadores OR que no son intercambiables. Esta página los cubre todos, además de las trampas de precedencia que producen respuestas silenciosamente incorrectas.
Aritméticos: +, -, *, /, ^, %% y %/%
Los cinco primeros hacen lo que esperas. Los dos envueltos en porcentajes - %% (módulo, el resto) y %/% (división entera, el cociente) - son los que la gente busca:
Fíjate en que / siempre hace división en coma flotante - 17 / 5 es 3.4, nunca 3. Si quieres la parte entera, para eso está exactamente %/%.
El trabajo cotidiano de %% es la divisibilidad. Un número es par cuando al dividirlo entre 2 no deja resto:
Esa segunda línea merece una pausa: con un operando negativo, el %% de R devuelve un resultado con el signo del divisor (-7 %% 3 es 2, porque -7 = -3 * 3 + 2). Algunos lenguajes lo hacen al revés; si estás portando código, compruébalo.
Los operadores de comparación están vectorizados
==, !=, <, <=, >, >= comparan elemento a elemento y devuelven un vector lógico, no una única respuesta:
Este es el motor detrás de casi todo el filtrado en R - comparas un vector entero contra un valor, obtienes una máscara lógica y usas la máscara para hacer el subconjunto. Una advertencia sobre == con decimales: los números en coma flotante se almacenan de forma aproximada, así que 0.1 + 0.2 == 0.3 es FALSE. Para comparar decimales, prefiere all.equal() o comprueba abs(x - y) < 1e-9.
Operadores lógicos: & frente a && (la confusión clásica)
R tiene dos operadores AND y dos operadores OR, y elegir el equivocado es un rito de paso.
& y | están vectorizados. Combinan dos vectores lógicos elemento a elemento:
Úsalos siempre que estés construyendo un filtro sobre datos: df[df$age > 30 & df$city == "Lisbon", ].
&& y || son escalares y hacen cortocircuito. Toman valores individuales, devuelven un único TRUE/FALSE y se saltan por completo el segundo operando si el primero ya resuelve la respuesta:
Esa segunda línea demuestra el cortocircuito: como x < 0 es FALSE, R nunca evalúa la llamada a stop(). Por eso exactamente && pertenece a las condiciones if() - puedes escribir if (!is.na(x) && x > 10) y la parte x > 10 se salta con seguridad cuando x es NA.
La regla general: &/| para vectores y filtrado de datos, &&/|| para condiciones if(). Y desde R 4.3 esto se impone con dientes: pasarle a && o || un vector de longitud mayor que 1 es un error (las versiones antiguas de R usaban en silencio solo el primer elemento, lo que ocultó errores reales durante años).
xor(a, b) completa el conjunto - TRUE cuando exactamente uno de los dos es TRUE:
%in%: comprobar pertenencia
x %in% table pregunta, para cada elemento de x: "¿aparece esto en algún lugar de table?". Es uno de los operadores más usados en el código real de R:
El lado que se comprueba puede ser un vector entero, lo que convierte a %in% en la herramienta natural para filtrar filas por un conjunto de valores permitidos.
También gana a la alternativa que si no escribirías - una cadena de == pegados con |:
Con cinco valores permitidos, la cadena de == se convierte en un muro de repetición; la versión con %in% solo hace crecer el vector. Hay una segunda ventaja, más sutil: %in% nunca devuelve NA:
NA == 1 es NA porque R no puede saber si un valor desconocido es igual a 1 - un comportamiento cubierto a fondo en valores ausentes. Ese NA luego envenena cualquier if() al que llegue. %in% esquiva todo el problema respondiendo siempre TRUE o FALSE, y por eso es la opción más segura para condiciones sobre datos que podrían faltar.
Trampas de precedencia
Dos trampas de precedencia de operadores explican una parte desproporcionada de los momentos "R está roto". Primera: ^ tiene más precedencia que el menos unario:
Segunda: los dos puntos tienen más precedencia que la aritmética binaria:
Ante la duda, añade paréntesis. No cuestan nada y cualquier lector (incluido tu yo futuro) los interpreta igual que el intérprete.
$ y [ ]: los operadores de acceso
También verás constantemente $, [ ] y [[ ]] - técnicamente también operadores, usados para extraer valores de estructuras en lugar de para calcular con ellos:
Se cubren a fondo en las páginas sobre vectores, listas y data frames - aquí basta con reconocerlos como miembros de la misma familia de operadores.
Lo que te llevas
%%da el resto,%/%el cociente entero;x %% 2 == 0comprueba si es par.- Las comparaciones están vectorizadas - devuelven un vector lógico con el que puedes filtrar.
&/|combinan vectores elemento a elemento;&&/||son para valores individuales enif()y hacen cortocircuito. Desde R 4.3,&&sobre un vector más largo es un error.x %in% tablesustituye a los==encadenados y nunca devuelveNA.-2^2es-4y1:n - 1empieza en 0 - pon paréntesis ante la duda.
Lo siguiente: poner estos operadores a trabajar dentro de if, else e ifelse() - las sentencias condicionales de R.
Preguntas frecuentes
¿Qué hace %% en R?
%% es el operador módulo - devuelve el resto de una división. 17 %% 5 es 2. Su compañero %/% hace la división entera y devuelve el cociente sin el resto: 17 %/% 5 es 3. El uso clásico de %% es comprobar si un número es par: x %% 2 == 0.
¿Cuál es la diferencia entre & y && en R?
& está vectorizado: compara dos vectores elemento a elemento y devuelve un vector de la misma longitud. && funciona solo con valores individuales, hace cortocircuito (se salta el segundo operando si el primero ya decide el resultado) y devuelve exactamente un TRUE o FALSE. Usa & al filtrar vectores y && dentro de condiciones if(). Desde R 4.3, pasar a && o || un vector de longitud mayor que 1 es un error, no un aviso.
¿Qué hace %in% en R?
x %in% table comprueba si cada elemento de x aparece en algún lugar de table, devolviendo TRUE o FALSE por elemento. "mango" %in% basket sustituye a una cadena de comparaciones == unidas con |, y a diferencia de == nunca devuelve NA - un valor ausente en el lado que se comprueba simplemente da FALSE.
¿Por qué -2^2 devuelve -4 en R?
Porque ^ tiene más precedencia que el menos unario, R lee -2^2 como -(2^2), que es -4. Si quieres decir el cuadrado de menos dos, escribe (-2)^2, que es 4. Los dos puntos tienen una trampa parecida: 1:n - 1 significa (1:n) - 1, no 1:(n - 1).