studio - superponer graficas en r
Cuente el nĂºmero de observaciones/filas por grupo y agregue el resultado al marco de datos (8)
El aggregate
función base R
obtendrá los recuentos con un solo liner, pero al agregar esos recuentos a los datos originales, el data.frame
parece tardar un poco de procesamiento.
df <- data.frame(name=c(''black'',''black'',''black'',''red'',''red''),
type=c(''chair'',''chair'',''sofa'',''sofa'',''plate''),
num=c(4,5,12,4,3))
df
# name type num
# 1 black chair 4
# 2 black chair 5
# 3 black sofa 12
# 4 red sofa 4
# 5 red plate 3
rows.per.group <- aggregate(rep(1, length(paste0(df$name, df$type))),
by=list(df$name, df$type), sum)
rows.per.group
# Group.1 Group.2 x
# 1 black chair 2
# 2 red plate 1
# 3 black sofa 1
# 4 red sofa 1
my.summary <- do.call(data.frame, rows.per.group)
colnames(my.summary) <- c(colnames(df)[1:2], ''rows.per.group'')
my.data <- merge(df, my.summary, by = c(colnames(df)[1:2]))
my.data
# name type num rows.per.group
# 1 black chair 4 2
# 2 black chair 5 2
# 3 black sofa 12 1
# 4 red plate 3 1
# 5 red sofa 4 1
Digamos que tengo un objeto data.frame
:
df <- data.frame(name=c(''black'',''black'',''black'',''red'',''red''),
type=c(''chair'',''chair'',''sofa'',''sofa'',''plate''),
num=c(4,5,12,4,3))
Ahora quiero contar el número de observaciones de cada combinación de name
y type
. Esto se puede hacer así:
table(df[ , c("name","type")])
o posiblemente también con plyr
, (aunque no estoy seguro de cómo).
Sin embargo, ¿cómo obtengo los resultados incorporados en el marco de datos original? Para que los resultados se vean así:
df
# name type num count
# 1 black chair 4 2
# 2 black chair 5 2
# 3 black sofa 12 1
# 4 red sofa 4 1
# 5 red plate 3 1
donde count
ahora almacena los resultados de la agregación.
Una solución con plyr
podría ser interesante para aprender también, aunque me gustaría ver cómo se hace esto con la base R.
Estabas a un paso de incorporar el recuento de filas en el conjunto de datos base.
Usando la función tidy()
del paquete broom
, convierta la tabla de frecuencias en un marco de datos y una unión interna con df
:
df <- data.frame(name=c(''black'',''black'',''black'',''red'',''red''),
type=c(''chair'',''chair'',''sofa'',''sofa'',''plate''),
num=c(4,5,12,4,3))
library(broom)
df <- merge(df, tidy(table(df[ , c("name","type")])), by=c("name","type"))
df
name type num Freq
1 black chair 4 2
2 black chair 5 2
3 black sofa 12 1
4 red plate 3 1
5 red sofa 4 1
Esto debería hacer tu trabajo:
df_agg <- aggregate(num~name+type,df,FUN=NROW)
names(df_agg)[3] <- "count"
df <- merge(df,df_agg,by=c(''name'',''type''),all.x=TRUE)
Otra forma que generaliza más:
df$count <- unsplit(lapply(split(df, df[c("name","type")]), nrow), df[c("name","type")])
Puedes hacerlo:
> ddply(df,.(name,type),transform,count = NROW(piece))
name type num count
1 black chair 4 2
2 black chair 5 2
3 black sofa 12 1
4 red plate 3 1
5 red sofa 4 1
o quizás más intuitivamente,
> ddply(df,.(name,type),transform,count = length(num))
name type num count
1 black chair 4 2
2 black chair 5 2
3 black sofa 12 1
4 red plate 3 1
5 red sofa 4 1
Puedes usar ave
:
df$count <- ave(df$num, df[,c("name","type")], FUN=length)
Una alternativa de dos líneas es generar una variable de 0 y luego completarla con split<-
, split
y lengths
como esta:
# generate vector of 0s
df$count <-0L
# fill it in
split(df$count, df[c("name", "type")]) <- lengths(split(df$num, df[c("name", "type")]))
Esto devuelve el resultado deseado
df
name type num count
1 black chair 4 2
2 black chair 5 2
3 black sofa 12 1
4 red sofa 4 1
5 red plate 3 1
Esencialmente, el RHS calcula las longitudes de cada combinación de nombre y tipo, devolviendo un vector con nombre de longitud 6 con 0 para "red.chair" y "black.plate". Esto se alimenta al LHS con split <-
que toma el vector y apropiadamente agrega los valores en sus puntos dados. Esto es esencialmente lo que ave
hace, como se puede ver que la segunda a la línea final de ave
es
split(x, g) <- lapply(split(x, g), FUN)
Sin embargo, lengths
es una versión optimizada de sapply(list, length)
.
Usando plyr
:
plyr::ddply(df, .(name, type), transform, count = length(num))
Usando data.table
:
library(data.table)
dt = data.table(df)
# using setkey or setkeyv to set the key
setkeyv(dt, c(''name'', ''type''))
# self
dt[dt[ , count = length(num), ''name, type'']]
EDITAR (mnel)
El uso de data.table
versión 1.8.2 o superior tiene :=
por grupo. También está el valor .N
(versión introducida 1.6.2), que es el número de filas del grupo, así que es tan fácil como
dt[ , count := .N, by = list(name, type)]
Usando dplyr
:
library(dplyr)
df %>%
group_by(name, type) %>%
mutate(count = n())
Con la nueva versión de dplyr
( 0.6.0
)
df %>%
add_count(name, type)