Combina marcos de datos desiguales y reemplaza las filas que faltan con 0

Tengo dos data.frames, uno con solo caracteres y el otro con caracteres y valores.

df1 = data.frame(x=c('a', 'b', 'c', 'd', 'e')) df2 = data.frame(x=c('a', 'b', 'c'),y = c(0,1,0)) merge(df1, df2) xy 1 a 0 2 b 1 3 c 0 

Quiero fusionar df1 y df2. Los caracteres a, b y c se fusionaron bien y también tienen 0, 1, 0 pero d y e no tienen nada. Quiero d y e también en la tabla de fusión, con la condición 0 0. Por lo tanto, para cada fila faltante en df2 data.frame, el 0 debe colocarse en la tabla df1, como:

  xy 1 a 0 2 b 1 3 c 0 4 d 0 5 e 0 

Eche un vistazo a la página de ayuda para fusionar. El parámetro all permite especificar diferentes tipos de fusiones. Aquí queremos establecer all = TRUE . Esto fusionará el retorno NA para los valores que no coinciden, que podemos actualizar a 0 con is.na() :

 zz <- merge(df1, df2, all = TRUE) zz[is.na(zz)] <- 0 > zz xy 1 a 0 2 b 1 3 c 0 4 d 0 5 e 0 

O, como alternativa al código de @ Chase, como fan de plyr reciente con experiencia en bases de datos:

 require(plyr) zz<-join(df1, df2, type="left") zz[is.na(zz)] <- 0 

Otra alternativa con data.table.

EJEMPLO DE DATOS

 dt1 <- data.table(df1) dt2 <- data.table(df2) setkey(dt1,x) setkey(dt2,x) 

CÓDIGO

 dt2[dt1,list(y=ifelse(is.na(y),0,y))] 

Utilicé la respuesta dada por Chase (respondida el 11 de mayo de 2011 a las 14:21), pero agregué un poco de código para aplicar esa solución a mi problema particular.

Tenía un marco de tasas (usuario, descarga) y un marco de totales (usuario, descarga) para fusionar por usuario, y quería incluir todas las tasas, incluso si no hubiera un total correspondiente. Sin embargo, no podría haber totales faltantes, en cuyo caso la selección de filas para el reemplazo de NA por cero fallaría.

La primera línea de código fusiona. Las siguientes dos líneas cambian los nombres de las columnas en el marco combinado. La instrucción if reemplaza NA por cero, pero solo si hay filas con NA.

 # merge rates and totals, replacing absent totals by zero graphdata <- merge(rates, totals, by=c("user"),all.x=T) colnames(graphdata)[colnames(graphdata)=="download.x"] = "download.rate" colnames(graphdata)[colnames(graphdata)=="download.y"] = "download.total" if(any(is.na(graphdata$download.total))) { graphdata[is.na(graphdata$download.total),]$download.total <- 0 }