r - tabla - Subconjunto con casos únicos, basado en múltiples columnas
seleccionar datos en r (5)
Me gustaría subconjuntar un marco de datos para incluir solo las filas que tienen combinaciones únicas de tres columnas. Mi situación es similar a la presentada en this pregunta, pero me gustaría conservar las otras columnas en mis datos también. Aquí está mi ejemplo:
> df
v1 v2 v3 v4 v5
1 7 1 A 100 98
2 7 2 A 98 97
3 8 1 C NA 80
4 8 1 C 78 75
5 8 1 C 50 62
6 9 3 C 75 75
El resultado solicitado sería algo como esto, en el que estoy buscando casos únicos basados en v1, v2 y v3 solamente:
> df.new
v1 v2 v3 v4 v5
1 7 1 A 100 98
2 7 2 A 98 97
3 8 1 C NA 80
6 9 3 C 75 75
Si pudiera recuperar las filas no exclusivas también sería genial:
> df.dupes
v1 v2 v3 v4 v5
3 8 1 C NA 80
4 8 1 C 78 75
5 8 1 C 50 62
Vi una pregunta relacionada sobre cómo hacer esto en sql ( here ), pero no puedo obtener esto en R. Estoy seguro de que es simple, pero jugar con unique () y subconjunto () no ha sido fructífero. Gracias por adelantado.
Puede usar la función duplicated()
para encontrar las combinaciones únicas:
> df[!duplicated(df[1:3]),]
v1 v2 v3 v4 v5
1 7 1 A 100 98
2 7 2 A 98 97
3 8 1 C NA 80
6 9 3 C 75 75
Para obtener solo los duplicados, puede verificarlo en ambas direcciones:
> df[duplicated(df[1:3]) | duplicated(df[1:3], fromLast=TRUE),]
v1 v2 v3 v4 v5
3 8 1 C NA 80
4 8 1 C 78 75
5 8 1 C 50 62
Puedes usar el paquete plyr
:
library(plyr)
ddply(df, c("v1","v2","v3"), head, 1)
# v1 v2 v3 v4 v5
# 1 7 1 A 100 98
# 2 7 2 A 98 97
# 3 8 1 C NA 80
# 4 9 3 C 75 75
ddply(df, c("v1","v2","v3"), function(x) if(nrow(x)>1) x else NULL)
# v1 v2 v3 v4 v5
# 1 8 1 C NA 80
# 2 8 1 C 78 75
# 3 8 1 C 50 62
Sí, pero usar plyr y ddply es muy lento si tienes demasiados datos.
Deberías intentar algo de este tipo:
df[ cbind( which(duplicated(df[1:3])), which(duplicated(df[1:3], fromLast=TRUE))),]
o::
from = which(duplicated(df[1:3])
to = which(duplicated(df[1:3], fromLast=TRUE))
df[cbind(from,to),]
SHD ser más rápido en su mayor parte.
pruébalo y haznos saber
hay algunos errores, pero supongo que puedes arreglarlos mientras tengas la idea.
También intente único y todo eso
Una forma no elegante pero funcional es pegar las entradas de una fila dada y encontrar cuáles son filas únicas (o no únicas), algo así como:
df.vector=apply(df,1,FUN=function(x) {paste(x,collapse="")})
df.table=table(df.vector)
luego obtenga los índices de los duplicados con algo como:
which(df.vector%in%names(which(df.table>1)))
Usando dplyr
puedes hacer:
library(dplyr)
# distinct
df %>%
distinct(v1, v2, v3, .keep_all = T)
# non-distinct only
df %>%
group_by(v1, v2, v3) %>%
filter(n() > 1)
# exclude any non-distinct
df %>%
group_by(v1, v2, v3) %>%
filter(n() == 1)