Contando Linhas por Grupo: table()
A pergunta de agrupamento mais simples é "quantos de cada?" - e o R base responde em uma única chamada. table() conta quantas vezes cada valor aparece:
Uma coluna dá as contagens por valor; duas colunas dão uma tabulação cruzada completa (regiões nas linhas, planos nas colunas). Para "qual proporção?", envolva em prop.table(table(...)). table() é o caminho mais rápido para uma resposta de frequência em todo o R - não recorra a nada mais pesado quando tudo que você precisa é de uma contagem.
Uma Estatística por Grupo: tapply()
tapply(values, groups, function) divide o primeiro vetor pelo segundo e aplica a função a cada pedaço:
O resultado é um vetor nomeado - rótulos dos grupos como nomes, estatísticas como valores - o que o torna perfeito para consultas rápidas (means["EU"]). O nome vem de "table apply": aplicar uma função ao longo de uma tabela de agrupamento. Ele pertence à mesma família de sapply() e lapply(), tratadas no doc da família apply.
O limite do tapply() é o formato: um vetor nomeado é desajeitado para fazer merge, plotar ou continuar processando. Quando o resumo é um degrau intermediário e não a resposta final, você quer um data frame de volta - que é exatamente o que a próxima ferramenta retorna.
O Cavalo de Batalha das Fórmulas: aggregate()
aggregate() é o group-by completo do R base: ele retorna um data frame, e sua interface de fórmula se lê como a frase que você diria. value ~ group significa "value, desagregado por group":
Adicionar agrupadores é só acrescentar + outra_coluna na fórmula - a segunda chamada soma por combinação de região e trimestre. Você também pode agregar várias colunas de valores de uma vez com cbind(a, b) ~ group. Como a saída é um data frame comum, ela se encaixa direto em um merge, uma ordenação ou um gráfico - esta é a ferramenta base padrão para resumos agrupados.
Um comportamento discreto que vale conhecer: a interface de fórmula descarta linhas com NA em qualquer coluna usada antes de agregar. Geralmente é o que você quer; ocasionalmente é a explicação para uma contagem que parece baixa.
O Jeito dplyr: group_by() + summarize()
O padrão moderno é o par de verbos do dplyr - group_by() declara o agrupamento, summarize() colapsa cada grupo em uma linha, calculando quantas estatísticas você nomear (estático; o sandbox roda apenas R base):
library(dplyr)
sales |>
group_by(region) |>
summarize(
n = n(),
total = sum(amount),
avg = mean(amount)
)
É aqui que o dplyr realmente supera o R base: várias estatísticas por grupo em uma chamada legível - aggregate() precisa de contorcionismos para isso - além de n() de graça, e o resultado flui direto para o próximo pipe. (summarise() é a mesma função, com grafia britânica.)
Uma coisa que confunde iniciantes: com vários agrupadores, summarize() remove apenas o último, deixando o resultado ainda agrupado - e imprime uma mensagem avisando. Diga explicitamente o que você quer com o argumento .groups: summarize(avg = mean(amount), .groups = "drop") retorna um data frame simples e desagrupado, que é o hábito padrão correto. Um data frame agrupado que escapa para o código posterior faz mutate() e companhia operarem silenciosamente por grupo - uma fonte clássica de resultados confusos.
Escolhendo Entre Elas
- Uma contagem -
table(), nada supera uma chamada só. - Uma estatística, olhada rápida -
tapply(), e leia a resposta direto do vetor nomeado. - Data frame na saída, ambiente só com R base -
aggregate()com uma fórmula. - Várias estatísticas, parte de um pipeline, ou qualquer coisa ambiciosa -
group_by() |> summarize().
Não há resposta errada entre elas - todas calculam os mesmos números - mas combinar a ferramenta com o formato de saída de que você precisa poupa a etapa de conversão depois. Médias, medianas e medidas de dispersão em si são tratadas em estatística descritiva.
Exemplo Prático: mtcars por Número de Cilindros
Tudo junto em um dataset embutido - por número de cilindros, quantos carros existem e qual a média de consumo e potência:
Onze carros de 4 cilindros com média de cerca de 26,7 mpg, sete de 6 cilindros em torno de 19,7, quatorze de 8 cilindros em torno de 15,1 - e a potência marchando na direção oposta. Duas chamadas, uma tabela-resumo completa: é para responder esse tipo de pergunta que a agregação por grupos existe.
O Que Você Leva
table()para contagens,prop.table()para proporções.tapply(values, groups, fn)retorna um vetor nomeado - olhadas rápidas, consultas fáceis.aggregate(value ~ group, data, FUN)retorna um data frame;+adiciona agrupadores,cbind()adiciona colunas de valores.- O
group_by() |> summarize(n = n(), avg = mean(x), .groups = "drop")do dplyr é o padrão moderno para resumos com várias estatísticas. - Escolha pelo formato de saída; todas concordam nos números.
A seguir: combinando tabelas que compartilham uma chave - merge() e a família de joins do dplyr.
Perguntas frequentes
Como calculo a média por grupo no R?
O R base tem duas ferramentas: tapply(df$value, df$group, mean) retorna um vetor nomeado com as médias de cada grupo, e aggregate(value ~ group, data = df, FUN = mean) retorna o mesmo resultado como data frame. No dplyr: df |> group_by(group) |> summarize(avg = mean(value)).
Como conto ocorrências por grupo no R?
table(df$group) conta as linhas por valor do grupo em uma única chamada; table(df$a, df$b) faz a tabulação cruzada de duas colunas. No dplyr, count(df, group) faz o mesmo e retorna um data frame, o que facilita continuar o processamento.
O que a função aggregate() faz no R?
aggregate() divide um data frame por uma ou mais colunas de agrupamento, aplica uma função a cada pedaço e retorna um data frame com os resultados. A interface de fórmula se lê naturalmente: aggregate(sales ~ region + quarter, data = df, FUN = mean) significa vendas, agrupadas por região e trimestre, com a média calculada.
Qual é a diferença entre tapply e aggregate?
Mesmo cálculo, formato de saída diferente. tapply() retorna um vetor nomeado (ou um array quando há dois agrupadores) - prático para consultas rápidas. aggregate() retorna um data frame - melhor quando o resultado alimenta uma análise posterior, um merge ou um gráfico. Na dúvida, aggregate().