Gli operatori che R ti mette a disposizione
Gli operatori di R si dividono in quattro gruppi: aritmetici (+ - * / ^ %% %/%), di confronto (== != < <= > >=), logici (& | && || ! xor) e il test di appartenenza %in%. Due cose li rendono diversi dalla maggior parte dei linguaggi: quasi tutti sono vettorizzati, cioè lavorano su interi vettori in una volta, elemento per elemento, e R ha due operatori AND e due operatori OR che non sono intercambiabili. Questa pagina li copre tutti, più le trappole di precedenza che producono risposte sbagliate senza avvisarti.
Aritmetica: +, -, *, /, ^, %% e %/%
I primi cinque fanno quello che ti aspetti. I due racchiusi tra segni di percentuale, %% (modulo, il resto) e %/% (divisione intera, il quoziente), sono quelli che la gente cerca:
Nota che / fa sempre una divisione in virgola mobile: 17 / 5 è 3.4, mai 3. Se vuoi la parte intera, è proprio a questo che serve %/%.
Il lavoro quotidiano di %% è la divisibilità. Un numero è pari quando la divisione per 2 non lascia resto:
Vale la pena soffermarsi sulla seconda riga: con un operando negativo, il %% di R restituisce un risultato con il segno del divisore (-7 %% 3 è 2, perché -7 = -3 * 3 + 2). Alcuni linguaggi fanno il contrario; se stai portando codice da un altro linguaggio, controlla.
Gli operatori di confronto sono vettorizzati
==, !=, <, <=, >, >= confrontano elemento per elemento e restituiscono un vettore logico, non una singola risposta:
È il motore dietro quasi tutti i filtri in R: confronti un intero vettore con un valore, ottieni una maschera logica e usi la maschera per estrarre un sottoinsieme. Una cautela con == sui decimali: i numeri in virgola mobile sono memorizzati in modo approssimato, quindi 0.1 + 0.2 == 0.3 è FALSE. Per confrontare decimali, preferisci all.equal() o verifica abs(x - y) < 1e-9.
Operatori logici: & contro && (la confusione classica)
R ha due operatori AND e due operatori OR, e scegliere quello sbagliato è un rito di passaggio.
& e | sono vettorizzati. Combinano due vettori logici elemento per elemento:
Usali ogni volta che costruisci un filtro sui dati: df[df$age > 30 & df$city == "Lisbon", ].
&& e || sono scalari e vanno in cortocircuito. Prendono singoli valori, restituiscono un singolo TRUE/FALSE e saltano del tutto il secondo operando se il primo decide già la risposta:
La seconda riga mostra il cortocircuito: dato che x < 0 è FALSE, R non valuta mai la chiamata a stop(). È esattamente per questo che && va nelle condizioni di if(): puoi scrivere if (!is.na(x) && x > 10) e la parte x > 10 viene saltata senza rischi quando x è NA.
La regola pratica: &/| per i vettori e il filtraggio dei dati, &&/|| per le condizioni di if(). E da R 4.3 la regola è imposta sul serio: passare a && o || un vettore di lunghezza maggiore di 1 è un errore (le versioni più vecchie di R usavano in silenzio solo il primo elemento, e questo ha nascosto bug reali per anni).
xor(a, b) completa il gruppo: TRUE quando esattamente uno dei due è TRUE.
%in%: verificare l'appartenenza
x %in% table chiede, per ogni elemento di x, "compare da qualche parte in table?". È uno degli operatori più usati nel codice R reale:
Il lato verificato può essere un intero vettore, e questo rende %in% lo strumento naturale per filtrare righe in base a un insieme di valori ammessi.
Batte anche l'alternativa che scriveresti altrimenti, una catena di == incollati con |:
Con cinque valori ammessi, la catena di == diventa un muro di ripetizioni; la versione con %in% allunga solo il vettore. C'è un secondo vantaggio, più sottile: %in% non restituisce mai NA:
NA == 1 è NA perché R non può sapere se un valore sconosciuto è uguale a 1, un comportamento trattato a fondo in valori mancanti. Quell'NA poi avvelena qualsiasi if() che raggiunge. %in% aggira del tutto il problema rispondendo sempre TRUE o FALSE, ed è per questo che è la scelta più sicura per le condizioni su dati che potrebbero mancare.
Trappole di precedenza
Due trappole di precedenza degli operatori sono responsabili di una quota sproporzionata di momenti "R è rotto". Primo, ^ ha la precedenza sul meno unario:
Secondo, i due punti hanno la precedenza sull'aritmetica binaria:
Nel dubbio, aggiungi le parentesi. Non costano niente e ogni lettore (compreso il te del futuro) le interpreta nello stesso modo dell'interprete.
$ e [ ]: gli operatori di accesso
Vedrai di continuo anche $, [ ] e [[ ]]: tecnicamente sono operatori anche loro, usati per estrarre valori dalle strutture invece che per calcolare:
Sono trattati per intero nelle pagine su vettori, liste e data frame; qui basta riconoscerli come membri della stessa famiglia di operatori.
Cosa ti porti a casa
%%dà il resto,%/%il quoziente intero;x %% 2 == 0verifica se un numero è pari.- I confronti sono vettorizzati: restituiscono un vettore logico con cui puoi filtrare.
&/|combinano vettori elemento per elemento;&&/||servono per singoli valori negliif()e vanno in cortocircuito. Da R 4.3,&&su un vettore più lungo è un errore.x %in% tablesostituisce le catene di==e non restituisce maiNA.-2^2è-4e1:n - 1parte da 0: nel dubbio, metti le parentesi.
Prossimo passo: mettere al lavoro questi operatori dentro if, else e ifelse(), le istruzioni condizionali di R.
Domande frequenti
Cosa fa %% in R?
%% è l'operatore modulo: restituisce il resto di una divisione. 17 %% 5 è 2. Il suo compagno %/% fa la divisione intera e restituisce il quoziente senza resto: 17 %/% 5 è 3. L'uso classico di %% è verificare se un numero è pari: x %% 2 == 0.
Qual è la differenza tra & e && in R?
& è vettorizzato: confronta due vettori elemento per elemento e restituisce un vettore della stessa lunghezza. && lavora solo su singoli valori, va in cortocircuito (salta il secondo operando se il primo decide già il risultato) e restituisce esattamente un TRUE o FALSE. Usa & quando filtri vettori, && dentro le condizioni di if(). Da R 4.3, passare a && o || un vettore più lungo di 1 è un errore, non un avviso.
Cosa fa %in% in R?
x %in% table verifica se ogni elemento di x compare da qualche parte in table, restituendo TRUE o FALSE per ogni elemento. "mango" %in% basket sostituisce una catena di confronti == uniti con |, e a differenza di == non restituisce mai NA: un valore mancante dal lato verificato dà semplicemente FALSE.
Perché -2^2 restituisce -4 in R?
Perché ^ ha la precedenza sul meno unario, R legge -2^2 come -(2^2), cioè -4. Se intendi il quadrato di meno due, scrivi (-2)^2, che è 4. I due punti hanno una trappola simile: 1:n - 1 significa (1:n) - 1, non 1:(n - 1).