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)
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. Posso realizar 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 o plyr é muito lento (quase inutilizável) quando o tamanho do conjunto de dados aumenta.
Como posso usar aggregate
ou outras funções para realizar vários cálculos em uma chamada?
aggregate
mencionado nas respostas, existem tambémby
etapply
.Respostas:
Você pode fazer tudo em uma etapa e obter a rotulagem adequada:
Isso cria um dataframe com duas colunas de id e duas colunas de matriz:
Como apontado por @ lord.garbage abaixo, isso pode ser convertido em um dataframe com colunas "simples" usando
do.call(data.frame, ...)
Esta é a sintaxe para várias variáveis no LHS:
fonte
d$val1[ , ""mn"]
e observe a estrutura comstr
.agg <- aggregate(cbind(val1, val2) ~ id1 + id2, data = x, FUN = function(x) c(mn = mean(x), n = length(x)))
usandoagg_df <- do.call(data.frame, agg)
. Veja também aqui .Dado isso na pergunta:
Em seguida, em
data.table
(1.9.4+
) você pode tentar:Para comparação de tempos
aggregate
(usado na pergunta e nas 3 outras respostas) paradata.table
ver este benchmark (os casosagg
eagg.x
).fonte
Você pode adicionar uma
count
coluna, agregar comsum
, em seguida, escalar para obtermean
:Tem a vantagem de preservar os nomes das colunas e criar uma única
count
coluna.fonte
Usando o
dplyr
pacote, você pode conseguir isso usandosummarise_all
. Com esta função de resumo, você pode aplicar outras funções (neste casomean
en()
) a cada uma das colunas não agrupadas:que dá:
Se você não quiser aplicar a (s) função (ões) a todas as colunas não agrupadas, especifique as colunas às quais elas devem ser aplicadas ou excluindo as não desejadas com um menos usando a
summarise_at()
função:fonte
Talvez você queira mesclar ?
fonte
Você também pode usar o
plyr::each()
para apresentar várias funções:fonte
Outra
dplyr
opção éacross
que faz parte da versão dev atualResultado
fonte