Filas colapsantes donde algunas son todas NA, otras son disjuntas con algunas NA

Tengo un dataframe simple como tal:

ID Col1 Col2 Col3 Col4 1 NA NA NA NA 1 5 10 NA NA 1 NA NA 15 20 2 NA NA NA NA 2 25 30 NA NA 2 NA NA 35 40 

Y me gustaría volver a formatearlo como tal:

 ID Col1 Col2 Col3 Col4 1 5 10 15 20 2 25 30 35 40 

(tenga en cuenta: el conjunto de datos real tiene miles de filas y los valores provienen de datos biológicos; las NA no siguen un patrón simple, excepto que las NA son disjuntas, y sí, hay exactamente 3 filas para cada ID ).

PASO UNO : deshazte de las filas que solo tienen valores de NA .

En la superficie esto parecía simple, pero me encontré con algunos problemas.

complete.cases(DF) devuelve todo FALSE , por lo que no puedo usar esto para eliminar las filas con todas las NA , como en DF[complete.cases(DF),] . Esto se debe a que todas las filas contienen al menos una NA .

Como las NA quieren propagarse, otros esquemas que usan is.na fallan por la misma razón.

PASO DOS : colapse las dos filas restantes en una.

Pensando en usar algo como aggregate para llevarlo a cabo, pero tiene que haber una manera más fácil que esto , que no funciona en absoluto.

Gracias por cualquier consejo.

Tratar

 library(dplyr) DF %>% group_by(ID) %>% summarise_each(funs(sum(., na.rm=TRUE))) 

Aquí hay un enfoque de tabla de datos que usa na.omit() en las columnas, agrupadas por ID.

 library(data.table) setDT(df)[, lapply(.SD, na.omit), by = ID] # ID Col1 Col2 Col3 Col4 # 1: 1 5 10 15 20 # 2: 2 25 30 35 40 

Aquí hay un par de bashs agregados:

 aggregate(. ~ ID, data=dat, FUN=na.omit, na.action="na.pass") # ID Col1 Col2 Col3 Col4 #1 1 5 10 15 20 #2 2 25 30 35 40 

Como aggregate interfaz de fórmula de aggregate usa na.omit forma predeterminada en toda la información antes de realizar cualquier agrupación, eliminará todas las filas de dat ya que todas contienen al menos un valor de NA . Pruébalo: nrow(na.omit(dat)) devuelve 0 . Entonces, en este caso, use na.pass en aggregate y luego na.omit para omitir las NA que se pasaron.

Alternativamente, no use la interfaz de fórmulas y especifique las columnas para agregarlas manualmente:

 aggregate(dat[-1], dat[1], FUN=na.omit ) aggregate(dat[c("Col1","Col2","Col3","Col4")], dat["ID"], FUN=na.omit) # ID Col1 Col2 Col3 Col4 #1 1 5 10 15 20 #2 2 25 30 35 40 

la manera simple es:

 as.data.frame(lapply(myData[,c('Col1','Col2','Col3','Col4')],function(x)[!is.na(x)])) 

pero si no todas las columnas tienen el mismo número de valores que no son NA , entonces tendrá que recortarlos de la siguiente manera:

 temp < - lapply(myData[,c('Col1','Col2','Col3','Col4')],function(x)x[!is.na(x)]) len <- min(sapply(temp,length)) as.data.frame(lapply(temp,`[`,seq(len)))