Eliminar grupos que tienen valores diferentes

Tengo un dataframe como a continuación

sample <- data.frame(ID=1:9, Group=c('AA','AA','AA','BB','BB','CC','CC','BB','CC'), Value = c(1,1,1,2,2,2,3,2,3)) 

Se supone que cada grupo tiene el mismo valor.

 ID Group Value 1 AA 1 2 AA 1 3 AA 1 4 BB 2 5 BB 2 6 CC 2 7 CC 3 8 BB 2 9 CC 3 

Si miras al grupo CC, no tiene el mismo valor. Varía con 2 y 3.

Necesito eliminar los grupos que no tienen un valor único.

En el caso anterior, el grupo CC debe eliminarse. El resultado debería ser como a continuación

 ID Group Value 1 AA 1 2 AA 1 3 AA 1 4 BB 2 5 BB 2 8 BB 2 

¿Me podría decir código simple y rápido en R que resuelve el problema?

Puede hacer un selector para la sample usando ave muchas maneras diferentes.

 sample[ ave( sample$Value, sample$Group, FUN = function(x) length(unique(x)) ) == 1,] 

o

 sample[ ave( sample$Value, sample$Group, FUN = function(x) sum(x - x[1]) ) == 0,] 

o

 sample[ ave( sample$Value, sample$Group, FUN = function(x) diff(range(x)) ) == 0,] 

Aquí hay una solución usando dplyr:

 library(dplyr) sample <- data.frame( ID = 1:9, Group= c('AA', 'AA', 'AA', 'BB', 'BB', 'CC', 'CC', 'BB', 'CC'), Value = c(1, 1, 1, 2, 2, 2, 3, 2, 3) ) sample %>% group_by(Group) %>% filter(n_distinct(Value) == 1) 

Agrupamos los datos por Group y luego solo seleccionamos los grupos donde el número de valores distintos de Value es 1.

versión data.table :

 library(data.table) sample <- as.data.table(sample) sample[,if(length(unique(Value))==1) .SD ,by=Group] # Group ID Value #1: AA 1 1 #2: AA 2 1 #3: AA 3 1 #4: BB 4 2 #5: BB 5 2 #6: BB 8 2 

Una alternativa que utiliza ave si los datos son numéricos, es verificar si la varianza es 0:

 sample[with(sample, ave(Value, Group, FUN=var ))==0,] 

Una solución alternativa que podría ser más rápida en datos grandes es:

 setkey(sample, Group, Value) ans <- sample[unique(sample)[, .N, by=Group][N==1, Group]] 

El punto es que el cálculo de valores unique para cada grupo puede consumir mucho tiempo cuando hay más grupos. En cambio, podemos establecer la clave en la data.table , luego tomar valores unique por clave (que es extremadamente rápido) y luego contar los valores totales para cada grupo. Luego requerimos solo aquellos en los que es 1. Entonces podemos realizar una join (que una vez más es muy rápida). Aquí hay un punto de referencia en datos grandes:

 require(data.table) set.seed(1L) sample <- data.table(ID=1:1e7, Group = sample(rep(paste0("id", 1:1e5), each=100)), Value = sample(2, 1e7, replace=TRUE, prob=c(0.9, 0.1))) system.time ( ans1 <- sample[,if(length(unique(Value))==1) .SD ,by=Group] ) # minimum of three runs # user system elapsed # 14.328 0.066 14.382 system.time ({ setkey(sample, Group, Value) ans2 <- sample[unique(sample)[, .N, by=Group][N==1, Group]] }) # minimum of three runs # user system elapsed # 5.661 0.219 5.877 setkey(ans1, Group, ID) setkey(ans2, Group, ID) identical(ans1, ans2) # [1] TRUE 

Aquí hay un enfoque

 > ind <- aggregate(Value~Group, FUN=function(x) length(unique(x))==1, data=sample)[,2] > sample[sample[,"Group"] %in% levels(sample[,"Group"])[ind], ] ID Group Value 1 1 AA 1 2 2 AA 1 3 3 AA 1 4 4 BB 2 5 5 BB 2 8 8 BB 2