Questo è un concetto ampio in R. Per orientarsi tra le varie possibilità, può essere utile considerare la dimensionalità dell'input e dell'output delle varie funzioni.
Abbiamo già visto funzioni che prendono in input un vettore e restituiscono un singolo valore di tipo scalare:
v <- 1:5
length(v)
#> [1] 5
sum(v)
#> [1] 15
Anche molte funzioni statistiche rientrano in questa categoria, come mean().
Per i vettori logici ci sono all() e any(), che restituiscono un unico TRUE o FALSE.
Molte funzioni in R operano su vettori interi, spesso restituendo un output vettoriale. Tra queste ci sono la maggior parte delle funzioni matematiche:
sq <- c(4, 9, 16, 25)
sqrt(sq) # square root
#> [1] 2 3 4 5
Non è solo una questione di concisione e comodità: si evita la necessità di cicli, list comprehension o ricorsione, comuni in altri linguaggi. In R, le funzioni vettoriali sono spesso molto più veloci di queste tecniche.
Hai già usato funzioni vettoriali più di quanto probabilmente immagini. Confronta questi esempi:
v <- c(2, 7, 9)
w <- c(3, 1, 5)
v + w
#> [1] 5 8 14
"+"(v, w)
#> [1] 5 8 14
I familiari operatori infissi non sono altro che zucchero sintattico per la funzione vettoriale sottostante! In questo caso "+"().
Per ordinare un vettore ci sono sort(), che restituisce i valori, e order(), che restituisce gli indici:
v <- c("I", "am", "not", "in", "order")
sort(v)
#> [1] "am" "I" "in" "not" "order"
order(v)
#> [1] 2 1 4 3 5
Per impostazione predefinita l'ordinamento è crescente.
Se serve, specifica decreasing = TRUE, oppure usa rev() per invertire un vettore esistente.
v <- c("I", "am", "not", "in", "order")
sort(v, decreasing = TRUE)
#> [1] "order" "not" "in" "I" "am"
rev(1:4)
#> [1] 4 3 2 1
Ci sono anche funzioni come cumsum() e cumprod() che producono output vettoriali cumulativi, operando sul vettore di input da sinistra a destra:
cumsum(1:5)
#> [1] 1 3 6 10 15 # sums
cumprod(1:5)
#> [1] 1 2 6 24 120 # equivalent to factorials
Gli esempi precedenti sono simili alle operazioni di foldl di molti linguaggi funzionali, con la differenza che l'output è un vettore con tutti i valori intermedi.
Un'estensione di questo concetto può essere usata anche per confrontare vettori.
Per esempio, considera la funzione di massimo a coppie pmax():
v
#> [1] 2 7 9
w
#> [1] 3 1 5
pmax(v, w)
#> [1] 3 7 9 # max of each pairwise comparison
Questa funzione, e altre simili, accettano anche un numero arbitrario di vettori di input, non solo due.
L'esempio precedente usa vettori di lunghezza uguale. Come discusso nel concetto Filtraggio dei vettori, R usa il riciclo per estendere i vettori che in qualche modo sono «troppo corti». Lo ripetiamo: usalo con cautela, e preferibilmente solo con un vettore di lunghezza 1.
pmax(v, 5)
#> [1] 5 7 9
Questo caso è meno comune, ma è abbastanza facile scrivere funzioni che, all'apparenza, prendono in input uno scalare e restituiscono un vettore.
Quando le si applica a un input vettoriale, l'output è una matrix bidimensionale (trattata in un concetto successivo).