Escenario
Estoy inspeccionando el Conjunto de datos sobre la soja en el que faltan bastantes valores de diversas variables categóricas.
Plan
Mi plan es acabar realizando la imputación de datos. Sin embargo, actualmente estoy tratando de entender el mecanismo detrás de estos valores perdidos (MAR, MNAR) utilizando gráficos, como se presentará a continuación.
Problema
Siento que he llegado a un punto muerto en lo que respecta a mi exploración: Soy incapaz de decidir si algunos datos son MAR o MNAR después de intentar varios gráficos. Agradecería mucho cualquier consejo o idea para comprender el mecanismo que hay detrás de mis valores de datos perdidos.
Código y gráficos
#load required libraries and data set
require(mlbench)
require(ggplot2)
require(vcd)
require(reshape2)
data(Soybean)
d1<- Soybean
#generate barplots for number of missing values and their proportion against variables
var.missing<- sapply(d1,function(x)sum(is.na(x)))
var.missing<- var.missing[order(var.missing)]
missing.df<- data.frame(variable=names(var.missing),missing=var.missing,missing.prop=var.missing/dim(d1)[1],stringsAsFactors=FALSE)
missing.df$variable<- factor(missing.df$variable,levels=missing.df$variable,ordered=FALSE)
g1<- ggplot(data=missing.df,aes(x=variable,y=missing)) + geom_bar() + labs(x="Variables",y="Number of missing values") + theme(axis.text.x=element_text(angle=45, hjust=1))
g2<- ggplot(data=missing.df,aes(x=variable,y=missing.prop)) + geom_bar() + labs(x="Variables",y="Proportion of missing values") + theme(axis.text.x=element_text(angle=45, hjust=1))
#so, lodging, seed.tmt, sever, hail have most missing values
#then come: germ, leaf.mild, shriveling, seed.discolor, fruiting.bodies, leaf.shred,
#seed.size, mold.growth, seed, fruit.pods, lead.malf, leaf.size, leaf.marg, leaf.halo
#let's check the proportion of missing values per class
df.per.class<- split(d1,d1$Class)
rows.per.class<- sapply(df.per.class, nrow)
tot.values.per.class<- sapply(rows.per.class,function(x)x*dim(d1)[2])
miss.per.class.usingRows<- sapply(df.per.class,function(x)apply(x,1,function(y)sum(is.na(y))))
miss.rows.per.class<- sapply(miss.per.class.usingRows,function(x)sum(x!=0))
miss.values.per.class<- sapply(miss.per.class.usingRows,sum)
miss.df.per.class<- data.frame(class=names(miss.values.per.class),total=tot.values.per.class,missing=miss.values.per.class,missProp=miss.values.per.class/tot.values.per.class,stringsAsFactors=FALSE)
miss.df.per.class<- miss.df.per.class[order(miss.df.per.class$total),]
miss.df.per.class$class<- factor(miss.df.per.class$class,levels=miss.df.per.class$class,ordered=FALSE)
melt.miss.df.class<- melt(miss.df.per.class[,c(1,2,3)],id.vars=1)
g3<- ggplot(data=melt.miss.df.class,aes(x=class,y=value)) + geom_bar(aes(fill=variable),position="identity") + labs(x="Classes",y="Values") + theme(axis.text.x=element_text(angle=45,hjust=1))
#now let's plot a heatmap for the proportion of missing values per classes against all variables
miss.per.class.usingCols<- sapply(df.per.class,function(x)apply(x,2,function(y)sum(is.na(y))))
miss.cols.per.class<- apply(miss.per.class.usingCols,2,function(y)sum(y!=0))
missing.melt<- melt(miss.per.class.usingCols)
values.per.class.usingCols<- sapply(df.per.class,function(x)apply(x,2,function(y)length(y)))
tot.values.melt<- melt(values.per.class.usingCols)
final.df<- data.frame(variables=missing.melt$Var1,classes=missing.melt$Var2,missing=missing.melt$value,total=tot.values.melt$value,missingProp=missing.melt$value/tot.values.melt$value)
g4<- ggplot(data=final.df,aes(x=classes,y=variables)) + geom_tile(aes(fill=missingProp)) + scale_fill_gradient(name="Proportion of missing values",low="white",high="red") + theme(axis.text.x=element_text(angle=45,hjust=1)) + labs(x="Classes",y="Variables")
Del gráfico anterior, puedo ver que hay ciertas variables que faltan para las 5 clases con datos faltantes, pero no sé si son MAR o MNAR.
He utilizado el siguiente código para comprobarlo:
selected<- miss.per.class.usingCols[,c("2-4-d-injury","cyst-nematode","diaporthe-pod-&-stem-blight","herbicide-injury","phytophthora-rot")]
all.missing<- apply(selected,1,function(x)all(x!=0)==TRUE)
all.missing
#hail, sever, seed.tmt, germ, leaf.mild, lodging
El único paso siguiente que se me ocurrió fue generar repetidamente gráficos de mosaico para diversas combinaciones de variables para ver si existe alguna relación.
Por ejemplo, he descubierto que tallo.cancros + cancro.lesión, cancro.lesión + descomposición.ext, y sever + semilla.tmt parecen mostrar algún patrón en el que todos los datos que faltan para una variable se producen en casos de datos que faltan para la otra.
#inspect using mosaic plots for categorical data
d2<- data.frame(as.matrix(d1),stringsAsFactors=FALSE)
d2[is.na(d2)]<- "NAs"
d3<- data.frame(sapply(d2,as.factor))
mosaic(xtabs(~d3$stem.cankers + d3$canker.lesion))
mosaic(xtabs(~d3$sever + d3$seed.tmt))
Pero no encuentro estos gráficos útiles para entender si mis datos son MAR o MNAR.
- ¿Existe alguna técnica mejor para mi propósito que yo desconozca?
- ¿Debo seguir trabajando con gráficos de mosaico para comprobar exhaustivamente cada par de variables?
- ¿Cómo encontraría estas relaciones en los datos? Agradeceríamos cualquier indicación o consejo.