renglones - sumar las filas de una matriz en r
¿Cómo sumar una variable por grupo? (10)
Aunque recientemente me he convertido en un convertidor a dplyr
para la mayoría de estos tipos de operaciones, el paquete sqldf
sigue siendo realmente bueno (y, en mi opinión, más legible) para algunas cosas.
Aquí hay un ejemplo de cómo esta pregunta puede ser respondida con sqldf
x <- data.frame(Category=factor(c("First", "First", "First", "Second",
"Third", "Third", "Second")),
Frequency=c(10,15,5,2,14,20,3))
sqldf("select
Category
,sum(Frequency) as Frequency
from x
group by
Category")
## Category Frequency
## 1 First 30
## 2 Second 5
## 3 Third 34
Digamos que tengo dos columnas de datos. El primero contiene categorías como "Primero", "Segundo", "Tercero", etc. El segundo tiene números que representan la cantidad de veces que vi "Primero".
Por ejemplo:
Category Frequency
First 10
First 15
First 5
Second 2
Third 14
Third 20
Second 3
Quiero ordenar los datos por Categoría y sumar las Frecuencias:
Category Frequency
First 30
Second 5
Third 34
¿Cómo haría esto en R?
Esto está algo relacionado con esta pregunta .
También puedes usar la función by () :
x2 <- by(x$Frequency, x$Category, sum)
do.call(rbind,as.list(x2))
Esos otros paquetes (plyr, reformar) tienen la ventaja de devolver un data.frame, pero vale la pena estar familiarizado con () ya que es una función básica.
La respuesta proporcionada por rcs funciona y es simple. Sin embargo, si está manejando conjuntos de datos más grandes y necesita un aumento de rendimiento, hay una alternativa más rápida:
library(data.table)
data = data.table(Category=c("First","First","First","Second","Third", "Third", "Second"),
Frequency=c(10,15,5,2,14,20,3))
data[, sum(Frequency), by = Category]
# Category V1
# 1: First 30
# 2: Second 5
# 3: Third 34
system.time(data[, sum(Frequency), by = Category] )
# user system elapsed
# 0.008 0.001 0.009
Comparemos eso con lo mismo usando data.frame y lo anterior:
data = data.frame(Category=c("First","First","First","Second","Third", "Third", "Second"),
Frequency=c(10,15,5,2,14,20,3))
system.time(aggregate(data$Frequency, by=list(Category=data$Category), FUN=sum))
# user system elapsed
# 0.008 0.000 0.015
Y si quieres mantener la columna esta es la sintaxis:
data[,list(Frequency=sum(Frequency)),by=Category]
# Category Frequency
# 1: First 30
# 2: Second 5
# 3: Third 34
La diferencia se hará más notoria con conjuntos de datos más grandes, como lo demuestra el siguiente código:
data = data.table(Category=rep(c("First", "Second", "Third"), 100000),
Frequency=rnorm(100000))
system.time( data[,sum(Frequency),by=Category] )
# user system elapsed
# 0.055 0.004 0.059
data = data.frame(Category=rep(c("First", "Second", "Third"), 100000),
Frequency=rnorm(100000))
system.time( aggregate(data$Frequency, by=list(Category=data$Category), FUN=sum) )
# user system elapsed
# 0.287 0.010 0.296
Para agregaciones múltiples, puede combinar lapply
y .SD
siguiente manera
data[, lapply(.SD, sum), by = Category]
# Category Frequency
# 1: First 30
# 2: Second 5
# 3: Third 34
Más recientemente, también puede usar el paquete dplyr para ese propósito:
library(dplyr)
x %>%
group_by(Category) %>%
summarise(Frequency = sum(Frequency))
#Source: local data frame [3 x 2]
#
# Category Frequency
#1 First 30
#2 Second 5
#3 Third 34
O, para múltiples columnas de resumen (también funciona con una columna):
x %>%
group_by(Category) %>%
summarise_each(funs(sum))
Actualización para dplyr> = 0.5: summarise_each
ha sido reemplazado por summarise_all
, summarise_at
& summarise_if
familia de funciones Summary en Dplyr.
O, si tiene varias columnas para agrupar, puede especificarlas todas en el group_by
separado por comas:
mtcars %>%
group_by(cyl, gear) %>% # multiple group columns
summarise(max_hp = max(hp), mean_mpg = mean(mpg)) # multiple summary columns
Para obtener más información, incluido el operador %>%
, consulte la introducción a dplyr .
Si x
es un marco de datos con sus datos, lo siguiente hará lo que desee:
require(reshape)
recast(x, Category ~ ., fun.aggregate=sum)
Solo para agregar una tercera opción:
require(doBy)
summaryBy(Frequency~Category, data=yourdataframe, FUN=sum)
EDIT: esta es una respuesta muy antigua. Ahora recomendaría el uso de group_by y resumiré desde dplyr, como en @docendo answer.
Utilizando aggregate
:
aggregate(x$Frequency, by=list(Category=x$Category), FUN=sum)
Category x
1 First 30
2 Second 5
3 Third 34
En el ejemplo anterior, se pueden especificar múltiples dimensiones en la list
. Se pueden incorporar múltiples métricas agregadas del mismo tipo de datos a través de cbind
:
aggregate(cbind(x$Frequency, x$Metric2, x$Metric3) ...
(incrustando el comentario de @thelatemail), el aggregate
tiene una interfaz de fórmula
aggregate(Frequency ~ Category, x, sum)
O si desea agregar varias columnas, puede usar el .
notación (funciona también para una columna)
aggregate(. ~ Category, x, sum)
o tapply
:
tapply(x$Frequency, x$Category, FUN=sum)
First Second Third
30 5 34
Utilizando estos datos:
x <- data.frame(Category=factor(c("First", "First", "First", "Second",
"Third", "Third", "Second")),
Frequency=c(10,15,5,2,14,20,3))
Varios años después, solo para agregar otra solución R de base simple que no está presente aquí por alguna razón: xtabs
xtabs(Frequency ~ Category, df)
# Category
# First Second Third
# 30 5 34
O si quieres un data.frame
vuelta
as.data.frame(xtabs(Frequency ~ Category, df))
# Category Freq
# 1 First 30
# 2 Second 5
# 3 Third 34
utilizando cast
lugar de recast
(la nota ''Frequency''
ahora es ''value''
)
df <- data.frame(Category = c("First","First","First","Second","Third","Third","Second")
, value = c(10,15,5,2,14,20,3))
install.packages("reshape")
result<-cast(df, Category ~ . ,fun.aggregate=sum)
Llegar:
Category (all)
First 30
Second 5
Third 34
library(plyr)
ddply(tbl, .(Category), summarise, sum = sum(Frequency))