tabla - Contraer el marco de datos seleccionando una fila por grupo
tabla de frecuencias en r (4)
Aquí hay una solución data.table
que será eficiente en tiempo y memoria para grandes conjuntos de datos
library(data.table)
DT <- as.data.table(d) # convert to data.table
setkey(DT, x) # set key to allow binary search using `J()`
DT[J(unique(x)), mult =''last''] # subset out the last row for each x
DT[J(unique(x)), mult =''first''] # if you wanted the first row for each x
Estoy intentando contraer un marco de datos eliminando todas las filas menos una de cada grupo de filas con valores idénticos en una columna en particular. En otras palabras, la primera fila de cada grupo.
Por ejemplo, me gustaría convertir este
> d = data.frame(x=c(1,1,2,4),y=c(10,11,12,13),z=c(20,19,18,17))
> d
x y z
1 1 10 20
2 1 11 19
3 2 12 18
4 4 13 17
Dentro de esto:
x y z
1 1 11 19
2 2 12 18
3 4 13 17
Estoy usando un agregado para hacer esto actualmente, pero el rendimiento es inaceptable con más datos:
> d.ordered = d[order(-d$y),]
> aggregate(d.ordered,by=list(key=d.ordered$x),FUN=function(x){x[1]})
He intentado dividir / no dividir con el mismo argumento de función que aquí, pero unsplit se queja de números de fila duplicados.
¿Es rle una posibilidad? ¿Existe un lenguaje R para convertir el vector de longitud de rle en los índices de las filas que comienzan cada ejecución, que luego puedo usar para arrancar esas filas fuera del marco de datos?
Hay un par de opciones usando dplyr
:
library(dplyr)
df %>% distinct(x, .keep_all = TRUE)
df %>% group_by(x) %>% filter(row_number() == 1)
df %>% group_by(x) %>% slice(1)
Puede usar más de una columna con las dos distinct()
y group_by()
:
df %>% distinct(x, y, .keep_all = TRUE)
El group_by()
y filter()
puede ser útil si hay una fecha o algún otro campo secuencial y usted quiere asegurarse de que se mantenga la observación más reciente, y la slice()
es útil si quiere evitar los vínculos:
df %>% group_by(x) %>% filter(date == max(date)) %>% slice(1)
Solo para agregar un poco a lo que proporcionó Dirk ... duplicated
tiene un argumento fromLast
que puede usar para seleccionar la última fila:
d[ !duplicated(d$x,fromLast=TRUE), ]
Tal vez duplicated()
puede ayudar:
R> d[ !duplicated(d$x), ]
x y z
1 1 10 20
3 2 12 18
4 4 13 17
R>
Editar Shucks, no importa. Esto elige el primero en cada bloque de repeticiones, usted quiso el último. Así que aquí hay otro intento usando plyr :
R> ddply(d, "x", function(z) tail(z,1))
x y z
1 1 11 19
2 2 12 18
3 4 13 17
R>
Aquí plyr realiza el arduo trabajo de encontrar subconjuntos únicos, repitiéndolos en bucle y aplicando la función suministrada, que simplemente devuelve el último conjunto de observaciones en un bloque z
usando tail(z, 1)
.