Contare le righe per gruppo: table()
La domanda di raggruppamento più semplice è "quanti di ciascuno?", e R base risponde in una sola chiamata. table() conta quante volte compare ogni valore:
Una colonna dà i conteggi per valore; due colonne danno una tabella di contingenza completa (regioni sulle righe, piani sulle colonne). Per sapere "che quota?" avvolgila in prop.table(table(...)). table() è la strada più rapida verso una risposta sulle frequenze in tutto R: non ricorrere a niente di più pesante quando ti serve solo un conteggio.
Una statistica per gruppo: tapply()
tapply(values, groups, function) divide il primo vettore secondo il secondo e applica la funzione a ogni pezzo:
Il risultato è un vettore con nomi, con le etichette dei gruppi come nomi e le statistiche come valori, ed è perfetto per consultazioni rapide (means["EU"]). Il nome si legge come "table apply": applicare una funzione lungo una tabella di raggruppamento. Appartiene alla stessa famiglia di sapply() e lapply(), trattate nella guida alla famiglia apply.
Il limite di tapply() è la forma: un vettore con nomi è scomodo da unire, rappresentare in un grafico o continuare a elaborare. Quando il riepilogo è un passaggio intermedio e non la risposta finale, vuoi indietro un data frame, ed è proprio quello che restituisce lo strumento successivo.
Il cavallo da tiro delle formule: aggregate()
aggregate() è il group-by completo di R base: restituisce un data frame, e la sua interfaccia a formula si legge come la frase che diresti. value ~ group significa "value, suddiviso per group":
Aggiungere raggruppatori è solo un + altra_colonna nella formula: la seconda chiamata somma per ogni combinazione di regione e trimestre. Puoi anche aggregare più colonne di valori insieme con cbind(a, b) ~ group. Dato che l'output è un normale data frame, si inserisce direttamente in un merge, un ordinamento o un grafico: è lo strumento base da usare di default per i riepiloghi per gruppo.
Un comportamento silenzioso da conoscere: l'interfaccia a formula scarta le righe con NA in una qualsiasi colonna usata prima di aggregare. Di solito è quello che vuoi; ogni tanto è la spiegazione di un conteggio che sembra basso.
Il modo dplyr: group_by() + summarize()
Lo standard moderno è lo schema a due verbi di dplyr: group_by() dichiara il raggruppamento, summarize() riduce ogni gruppo a una riga, calcolando tutte le statistiche che nomini (statico; la sandbox esegue solo R base):
library(dplyr)
sales |>
group_by(region) |>
summarize(
n = n(),
total = sum(amount),
avg = mean(amount)
)
Qui dplyr supera davvero R base: più statistiche per gruppo in una sola chiamata leggibile (a aggregate() servono contorsioni per farlo), in più n() gratis, e il risultato scorre dritto nella pipe successiva. (summarise() è la stessa funzione, con la grafia britannica.)
Una cosa che spiazza chi inizia: con più raggruppatori, summarize() toglie solo l'ultimo, lasciando il risultato ancora raggruppato, e stampa un messaggio a riguardo. Di' esplicitamente cosa vuoi con l'argomento .groups: summarize(avg = mean(amount), .groups = "drop") restituisce un data frame semplice, non raggruppato, ed è la buona abitudine di default. Un data frame raggruppato che si infila nel codice successivo fa lavorare mutate() e compagnia per gruppo senza avvisarti: una fonte classica di risultati confusi.
Come scegliere tra loro
- Un conteggio:
table(), niente batte una sola chiamata. - Una statistica, un'occhiata veloce:
tapply(), e leggi la risposta dal vettore con nomi. - Data frame in uscita, ambiente solo base:
aggregate()con una formula. - Più statistiche, parte di una pipeline, o qualsiasi cosa ambiziosa:
group_by() |> summarize().
Non c'è una risposta sbagliata tra queste: calcolano tutte gli stessi numeri. Ma scegliere lo strumento in base alla forma di output che ti serve ti risparmia il passaggio di conversione dopo. Medie, mediane e dispersioni vere e proprie sono trattate in statistica descrittiva.
Esempio svolto: mtcars per numero di cilindri
Tutto insieme su un dataset integrato: per numero di cilindri, quante auto ci sono e i loro consumi e potenza medi:
Undici auto a 4 cilindri con una media di circa 26.7 mpg, sette a 6 cilindri intorno a 19.7, quattordici a 8 cilindri intorno a 15.1, e la potenza che va nella direzione opposta. Due chiamate, un'intera tabella di riepilogo: è proprio il tipo di domanda a cui serve l'aggregazione per gruppi.
Cosa ti porti a casa
table()per i conteggi,prop.table()per le quote.tapply(values, groups, fn)restituisce un vettore con nomi: occhiate veloci, consultazioni facili.aggregate(value ~ group, data, FUN)restituisce un data frame;+aggiunge raggruppatori,cbind()aggiunge colonne di valori.- Il
group_by() |> summarize(n = n(), avg = mean(x), .groups = "drop")di dplyr è lo standard moderno per riepiloghi con più statistiche. - Scegli in base alla forma dell'output; sui numeri sono tutti d'accordo.
Prossimo passo: combinare tabelle che condividono una chiave, con merge() e la famiglia di join di dplyr.
Domande frequenti
Come si calcola la media per gruppo in R?
R base ha due strumenti: tapply(df$value, df$group, mean) restituisce un vettore con nomi delle medie per gruppo, e aggregate(value ~ group, data = df, FUN = mean) restituisce lo stesso risultato come data frame. In dplyr: df |> group_by(group) |> summarize(avg = mean(value)).
Come si contano le occorrenze per gruppo in R?
table(df$group) conta le righe per ogni valore del gruppo in una sola chiamata; table(df$a, df$b) incrocia due colonne in una tabella di contingenza. In dplyr, count(df, group) fa lo stesso e restituisce un data frame, più comodo da continuare a elaborare.
Cosa fa aggregate() in R?
aggregate() divide un data frame secondo una o più colonne di raggruppamento, applica una funzione a ogni pezzo e restituisce un data frame di risultati. L'interfaccia a formula si legge in modo naturale: aggregate(sales ~ region + quarter, data = df, FUN = mean) significa sales, raggruppato per region e quarter, in media.
Qual è la differenza tra tapply e aggregate?
Stesso calcolo, forma di output diversa. tapply() restituisce un vettore con nomi (o un array con due raggruppatori): comodo per consultazioni rapide. aggregate() restituisce un data frame: meglio quando il risultato alimenta altre analisi, un merge o un grafico. Nel dubbio, aggregate().