2012-06-08 13 views
10

lo tanto, tengo una trama de datos con dos factores y una variable numérica así:Manipulación combinaciones de factores de falta en R

>D 
f1 f2 v1 
1 A 23 
2 A 45 
2 B 27 
    . 
    . 
    . 

por lo que los niveles de F1 son 1 y 2 y los niveles de f2 son A y B. Aquí está la cosa, no hay ningún valor ingresado para cuando f1 = 1 y f2 = B (que es D $ V1 [D $ f1 = 1 & D $ f2 = B] no está allí) en realidad esto debería ser cero.

En mi marco de datos real tengo 11 niveles de f1 y cerca de 150 niveles de f2 y necesito crear una observación con v1 = 0 para cada combinación de f1 y f2 que falta en mi marco de datos.

¿Cómo voy a ir haciendo esto?

Gracias de antemano,

Ian

Respuesta

11

Uso de sus datos:

dat <- data.frame(f1 = factor(c(1,2,2)), f2 = factor(c("A","A","B")), 
        v1 = c(23,45,27)) 

una opción es crear una tabla de consulta con las combinaciones de niveles, que se realiza mediante la función expand.grid() suministrado con los niveles de ambos factores, como se muestra a continuación:

dat2 <- with(dat, expand.grid(f1 = levels(f1), f2 = levels(f2))) 

Una base de datos similar a unirse operación entonces puede realizarse usando la función de merge() en el que se especifica que todos los valores desde la tabla de búsqueda se incluyen en la unión (all.y = TRUE)

newdat <- merge(dat, dat2, all.y = TRUE) 

La línea anterior produce:

> newdat 
    f1 f2 v1 
1 1 A 23 
2 1 B NA 
3 2 A 45 
4 2 B 27 

Como puede ver, las combinaciones que faltan reciben el valor NA que indica la falta. Es realtively sencilla a continuación, reemplazar estos NA s con 0 s:

> newdat$v1[is.na(newdat$v1)] <- 0 
> newdat 
    f1 f2 v1 
1 1 A 23 
2 1 B 0 
3 2 A 45 
4 2 B 27 
+0

@ user1443010 en esa línea, lo estoy usando para evitar 'dat $ f1' y' dat $ f2'. También creo que aclara la intención; usando * este * objeto, haz * que *. No hay nada de malo en esto a nivel de usuario, pero hay una penalización de eficiencia ya que R tiene que crear un nuevo entorno con el contenido del objeto y eso lleva tiempo. 'dat2 <- expand.grid (f1 = levels (dat $ f1), f2 = levels (dat $ f2))' sería la alternativa. No siempre se puede trabajar cosas en un 'con()'; No creo que la línea que reemplaza 'NA 'pueda transformarse fácilmente en' con() ', pero me puede faltar algo. –

+0

increíble! ¡Gracias! ;) – maycca

1

Dos años más tarde, pero no tenía el mismo problema y se acercó con esta solución plyr:

dat <- data.frame(f1 = factor(c(1,2,2)), f2 = factor(c("A","A","B")), v1 = c(23,45,27)) 

newdat <- ddply(dat, .(f1,f2), numcolwise(function(x) {if(length(x)>0) x else 0.0}), .drop=F) 

> newdat 
    f1 f2 v1 
1 1 A 23 
2 1 B 0 
3 2 A 45 
4 2 B 27 
2

añado el tidyr solución, extendiendo con fill=0 y reuniendo.

library(tidyr) 
df %>% spread(f2, v1, fill=0) %>% gather(f2, v1, -f1) 

# f1 f2 v1 
#1 1 A 23 
#2 2 A 45 
#3 1 B 0 
#4 2 B 27 

También podría hacer df %>% spread(f1, v1, fill=0) %>% gather(f1, v1, -f2).

Cuestiones relacionadas