Aplicar várias funções de resumo em várias variáveis ​​por grupo em uma chamada

Eu tenho o seguinte quadro de dados

x <- read.table(text = "  id1 id2 val1 val2
1   a   x    1    9
2   a   x    2    4
3   a   y    3    5
4   a   y    4    9
5   b   x    1    7
6   b   y    4    4
7   b   x    3    9
8   b   y    2    8", header = TRUE)

Eu quero calcular a média de val1 e val2 agrupados por id1 e id2 e, simultaneamente, contar o número de linhas para cada combinação id1-id2. Eu posso executar cada cálculo separadamente:

# calculate mean
aggregate(. ~ id1 + id2, data = x, FUN = mean)

# count rows
aggregate(. ~ id1 + id2, data = x, FUN = length)

Para fazer os dois cálculos em uma chamada, tentei

do.call("rbind", aggregate(. ~ id1 + id2, data = x, FUN = function(x) data.frame(m = mean(x), n = length(x))))

No entanto, recebo uma saída distorcida junto com um aviso:

#     m   n
# id1 1   2
# id2 1   1
#     1.5 2
#     2   2
#     3.5 2
#     3   2
#     6.5 2
#     8   2
#     7   2
#     6   2
# Warning message:
#   In rbind(id1 = c(1L, 2L, 1L, 2L), id2 = c(1L, 1L, 2L, 2L), val1 = list( :
#   number of columns of result is not a multiple of vector length (arg 1)

Eu poderia usar o pacote plyr, mas meu conjunto de dados é muito grande e plyr é muito lento (quase inutilizável) quando o tamanho do conjunto de dados aumenta.

Como posso usaraggregate ou outras funções para realizar vários cálculos em uma chamada?

questionAnswers(6)

yourAnswerToTheQuestion