Numeric e integer: i due tipi di numero di R
R memorizza i numeri in due modi. Numeric (memorizzato come numero in virgola mobile a doppia precisione) è il default: ogni numero che scrivi è un double, a meno che tu non dica altrimenti. Integer è un tipo separato per numeri interi esatti, che richiedi con il suffisso L:
Nella pratica raramente devi preoccupartene: R converte dall'uno all'altro in silenzio, e is.numeric() è TRUE per entrambi (vedi tipi di dati per il sistema dei tipi completo). L'unico punto in cui la distinzione si vede è la divisione: / restituisce sempre un double, anche tra due interi:
Gli interi compaiono soprattutto come risultato di funzioni di conteggio (length(), seq_len(), nrow()) e come valori di indice. Quando ti serve la divisione intera, R ha un operatore dedicato, che vediamo più avanti.
La famiglia degli arrotondamenti
R ti dà cinque modi per accorciare un numero, ognuno con un significato preciso:
round(x, digits): a un certo numero di cifre decimali (0 di default).floor(x): per difetto all'intero più vicino, sempre verso meno infinito.ceiling(x): per eccesso, sempre verso più infinito.trunc(x): taglia i decimali, sempre verso zero. Nota la differenza sui negativi:trunc(-2.7)è-2, mafloor(-2.7)è-3.signif(x, digits): a un certo numero di cifre significative, non di cifre decimali:signif(123456, 2)è120000.
E una sorpresa famosa: sulle metà esatte round() usa l'arrotondamento half to even (arrotondamento del banchiere), secondo lo standard IEEE 754:
Stampa 0 2 2 4: ogni metà viene arrotondata al numero pari più vicino. Non è un bug; evita una distorsione sistematica verso l'alto quando sommi tanti valori arrotondati. Se un report ha bisogno dell'arrotondamento scolastico, aggiungi una piccola spinta o formatta i numeri al momento della presentazione.
Funzioni matematiche di tutti i giorni
Le basi funzionano esattamente come ti aspetti:
sqrt() è la radice quadrata, abs() il valore assoluto, ^ l'elevamento a potenza, e exp(x) è e elevato alla x, quindi exp(1) è il numero di Eulero, circa 2.718282.
L'unica funzione che fa inciampare è log(). In R, log() è il logaritmo naturale (base e), non in base 10:
La prima riga stampa circa 4.60517, non il 2 che si aspetta chi ragiona in base 10. Usa log10() e log2() quando intendi quelle basi, oppure passa base = in modo esplicito. (Questa convenzione è standard in statistica, dove il logaritmo naturale è quello predefinito.)
Modulo %% e divisione intera %/%
Due operatori coprono l'aritmetica dei resti:
%% è il modulo (resto): 17 diviso 5 fa 3 con resto 2. %/% è la divisione intera: quanti 5 interi stanno in 17. Insieme soddisfano x == (x %/% y) * y + (x %% y).
L'uso classico di %% è verificare la divisibilità:
Una sottigliezza con i numeri negativi: il %% di R prende il segno del divisore (come Python, a differenza di C):
Il risultato è 2, non -1: R risponde alla domanda "cosa aggiungo a un multiplo di 3 per arrivare a -7?", e così i risultati restano in 0..2 per un divisore positivo. Comodo per far ricominciare gli indici da capo; sorprendente se vieni da C o Java.
Valori speciali: Inf, -Inf e NaN
I numeri di R seguono lo standard IEEE 754, quindi alcune operazioni producono valori speciali invece di errori:
1/0 è Inf (infinito), -1/0 è -Inf, e 0/0, una quantità davvero indefinita, è NaN, "not a number". La distinzione conta: Inf è una risposta ("più grande di qualsiasi cosa"), NaN è l'assenza di una risposta. Li verifichi con funzioni dedicate, perché == NaN non funziona mai:
Nota l'ultima riga: anche NaN conta come NA, quindi is.na() lo intercetta, un motivo in più per cui is.na() è il controllo standard per "questo valore è inutilizzabile?" (approfondimenti in valori mancanti).
R legge e scrive anche la notazione scientifica in modo nativo: 2.5e3 è 2500, e i numeri molto piccoli o molto grandi vengono stampati in notazione e di default:
Usa format(x, scientific = FALSE) (o l'opzione scipen) quando un report ha bisogno di decimali normali.
La sorpresa della virgola mobile
Tutti i linguaggi che memorizzano i decimali in binario condividono questa, e R non fa eccezione:
FALSE, perché 0.1 + 0.2 in realtà vale 0.30000000000000004. Né 0.1 né 0.2 hanno una rappresentazione binaria esatta, e i piccoli errori si accumulano. La stampa predefinita di R lo nasconde mostrando 7 cifre significative, ed è per questo che il problema sembra invisibile finché un confronto con == non fallisce.
La regola: non confrontare mai decimali calcolati con ==. Usa all.equal(), che confronta entro una tolleranza sensata:
Avvolgilo in isTRUE() perché, quando i valori differiscono, all.equal() restituisce una descrizione della differenza (non FALSE). Per il lavoro con numeri interi in cui l'esattezza conta, gli integer sono esatti fino a circa 2.1 miliardi: un altro motivo per cui il codice di conteggio usa il tipo integer.
Cosa ti porti a casa
- Ogni numero che scrivi è un double;
42Lcrea un integer, e/restituisce comunque un double. round()arrotonda le metà al pari;floor/ceiling/trunc/signifaccorciano ciascuno in modo diverso: sappi quale intendi.log()è il logaritmo naturale; usalog10(),log2()obase =per le altre basi.%%dà il resto (il segno segue il divisore),%/%il quoziente intero.1/0èInf,0/0èNaN, e0.1 + 0.2 != 0.3: confronta i decimali conall.equal(), mai con==.
Prossimo passo: l'altra metà dei dati di tutti i giorni, le stringhe, e le funzioni che R ti dà per costruirle, formattarle e cercarci dentro.
Domande frequenti
Qual è la differenza tra numeric e integer in R?
Numeric (double) è il tipo predefinito di R per qualsiasi numero che scrivi: 42 è un double anche se sembra intero. Integer è un tipo di memorizzazione separato che richiedi con il suffisso L: 42L. La divisione normale restituisce sempre un double, anche tra interi; usa %/% per la divisione intera.
log() in R è il logaritmo naturale?
Sì: log(x) in R è il logaritmo naturale (base e), non in base 10. Usa log10() per la base 10, log2() per la base 2, oppure log(x, base = b) per qualsiasi base. log(100) vale circa 4.605, non 2.
Come funziona round() in R?
round(x, digits) arrotonda al numero di cifre decimali indicato, ma le metà esatte usano l'arrotondamento "half to even" (arrotondamento del banchiere): round(2.5) è 2 e round(3.5) è 4. Segue lo standard IEEE 754 e riduce la distorsione quando sommi valori arrotondati, ma sorprende chi si aspetta l'arrotondamento imparato a scuola.
Perché 0.1 + 0.2 non è uguale a 0.3 in R?
I double sono memorizzati in binario, e 0.1, 0.2 e 0.3 non hanno una rappresentazione binaria esatta, quindi 0.1 + 0.2 in realtà vale 0.30000000000000004. Non confrontare mai decimali calcolati con ==; usa isTRUE(all.equal(x, y)) oppure verifica abs(x - y) < 1e-9.