2012-08-30 40 views
24

Me pregunto cómo se puede agregar otra capa de complejidad importante y necesaria a un mapa de calor de correlación matricial como, por ejemplo, el valor p después del nivel de significancia de estrellas además del valor R2 (-1 a 1)
NO SE PRETENDIÓ en esta pregunta para poner estrellas de nivel de significancia O los valores de p como texto en cada cuadrado de la matriz PERO más bien para mostrar esto en una representación gráfica lista para usar del nivel de significancia en cada cuadrado de la matriz. Creo que solo aquellos que disfrutan la bendición del pensamiento INNOVADOR pueden ganar el aplauso para desentrañar este tipo de solución con el fin de tener la mejor manera de representar ese componente adicional de complejidad en nuestros "mapas de calor de correlación matricial a medias verdad". Busqué mucho en Google, pero nunca he visto una forma adecuada, o diría que respetuosa, de representar el nivel de significancia MÁS las sombras de colores estándar que reflejan el coeficiente R.
Los datos reproducibles establecidos se encuentra aquí:
http://learnr.wordpress.com/2010/01/26/ggplot2-quick-heatmap-plotting/
El código R se adjunta a continuación:Nivel de importancia agregado al mapa de calor de correlación matricial usando ggplot2

library(ggplot2) 
library(plyr) # might be not needed here anyway it is a must-have package I think in R 
library(reshape2) # to "melt" your dataset 
library (scales) # it has a "rescale" function which is needed in heatmaps 
library(RColorBrewer) # for convenience of heatmap colors, it reflects your mood sometimes 
nba <- read.csv("http://datasets.flowingdata.com/ppg2008.csv") 
nba <- as.data.frame(cor(nba[2:ncol(nba)])) # convert the matrix correlations to a dataframe 
nba.m <- data.frame(row=rownames(nba),nba) # create a column called "row" 
rownames(nba) <- NULL #get rid of row names 
nba <- melt(nba) 
nba.m$value<-cut(nba.m$value,breaks=c(-1,-0.75,-0.5,-0.25,0,0.25,0.5,0.75,1),include.lowest=TRUE,label=c("(-0.75,-1)","(-0.5,-0.75)","(-0.25,-0.5)","(0,-0.25)","(0,0.25)","(0.25,0.5)","(0.5,0.75)","(0.75,1)")) # this can be customized to put the correlations in categories using the "cut" function with appropriate labels to show them in the legend, this column now would be discrete and not continuous 
nba.m$row <- factor(nba.m$row, levels=rev(unique(as.character(nba.m$variable)))) # reorder the "row" column which would be used as the x axis in the plot after converting it to a factor and ordered now 
#now plotting 
ggplot(nba.m, aes(row, variable)) + 
geom_tile(aes(fill=value),colour="black") + 
scale_fill_brewer(palette = "RdYlGn",name="Correlation") # here comes the RColorBrewer package, now if you ask me why did you choose this palette colour I would say look at your battery charge indicator of your mobile for example your shaver, won't be red when gets low? and back to green when charged? This was the inspiration to choose this colour set. 

La matriz de correlación mapa de calor debe tener este aspecto:
enter image description here

Sugerencias e ideas para mejorar la solución:
- Este código puede ser útil para tener una idea sobre el nivel de significancia de las estrellas tomadas de este sitio web:
http://ohiodata.blogspot.de/2012/06/correlation-tables-in-r-flagged-with.html
código R:

mystars <- ifelse(p < .001, "***", ifelse(p < .01, "** ", ifelse(p < .05, "* ", " "))) # so 4 categories 

- El nivel de significación se puede añadir como intensidad de color a cada plaza como la estética alfa, pero no creo que esto será fácil de interpretar y captar
- Otra idea sería tener 4 tamaños diferentes de cuadrados correspondientes a las estrellas, por supuesto, dando el más pequeño al no significativo y aumenta a un tamaño completo cuadrado si las estrellas más altas
- Otra idea para incluir un círculo dentro de esos cuadrados significativos y el grosor de la línea del círculo corresponde al nivel de significancia (las 3 categorías restantes) todos ellos de un solo color
- Igual que el anterior pero que fija el grosor de la línea mientras da 3 colores para los 3 niveles significativos restantes
- ¿Puede venir con mejores ideas, quién sabe?

+2

Su código me inspiró a reescribir la función 'arm :: corrplot' con ggplot2: http: // rpubs.com/briatte/ggcorr –

+0

¡funciona genial! ¿Puede extender esta función para que desaparezcan esas correlaciones no significativas (por ejemplo, <0.05), manteniendo esas o igual a las anteriores? Aquí, uno debe alimentar la función con otra matriz PERO con valores p, comparto contigo esta función que puede ser de ayuda para obtener esa matriz p (puedes usar: cor.prob.all() cor.prob.all <- función (X, dfr = nrow (X) - 2) { R <- cor (X, use = "pairwise.complete.obs", method = "spearman") r2 <- R^2 Fstat <- r2 * dfr/(1 - r2) R <- 1 - pf (Fstat, 1, dfr) R [fila (R) == col (R)] <- NA R } – doctorate

+0

Gracias por su respuesta. Soy escéptico sobre el uso de $ p $ -valores aquí (y en otros lugares), pero voy a tratar de encontrar algo para marcar coeficientes insignificantes. –

Respuesta

25

Esto es solo un intento de mejorar hacia la solución final, tracé las estrellas aquí como indicador de la solución, pero como dije el objetivo es encontrar una solución gráfica que pueda hablar mejor que las estrellas. Acabo de utilizar geom_point y alpha para indicar el nivel de significancia, pero el problema es que las NA (que también incluyen los valores no significativos) se mostrarán como el nivel de significancia de tres estrellas, ¿cómo solucionarlo? Creo que usar un solo color puede ser más fácil de usar cuando se usan muchos colores y evitar cargar la trama con muchos detalles para que los ojos se resuelvan. Gracias por adelantado.
Aquí es la trama de mi primer intento:
enter image description here

o podría ser esto mejor ?!
enter image description here

Creo que lo mejor hasta ahora es el siguiente, hasta que se te ocurra algo mejor! enter image description here

Conforme a lo solicitado, el código de abajo es para el último mapa de calor:

# Function to get the probability into a whole matrix not half, here is Spearman you can change it to Kendall or Pearson 
cor.prob.all <- function (X, dfr = nrow(X) - 2) { 
R <- cor(X, use="pairwise.complete.obs",method="spearman") 
r2 <- R^2 
Fstat <- r2 * dfr/(1 - r2) 
R<- 1 - pf(Fstat, 1, dfr) 
R[row(R) == col(R)] <- NA 
R 
} 
# Change matrices to dataframes 
nbar<- as.data.frame(cor(nba[2:ncol(nba)]),method="spearman") # to a dataframe for r^2 
nbap<- as.data.frame(cor.prob.all(nba[2:ncol(nba)])) # to a dataframe for p values 
# Reset rownames 
nbar <- data.frame(row=rownames(nbar),nbar) # create a column called "row" 
rownames(nbar) <- NULL 
nbap <- data.frame(row=rownames(nbap),nbap) # create a column called "row" 
rownames(nbap) <- NULL 
# Melt 
nbar.m <- melt(nbar) 
nbap.m <- melt(nbap) 
# Classify (you can classify differently for nbar and for nbap also)   
nbar.m$value2<-cut(nbar.m$value,breaks=c(-1,-0.75,-0.5,-0.25,0,0.25,0.5,0.75,1),include.lowest=TRUE, label=c("(-0.75,-1)","(-0.5,-0.75)","(-0.25,-0.5)","(0,-0.25)","(0,0.25)","(0.25,0.5)","(0.5,0.75)","(0.75,1)")) # the label for the legend 
nbap.m$value2<-cut(nbap.m$value,breaks=c(-Inf, 0.001, 0.01, 0.05),label=c("***", "** ", "* ")) 
nbar.m<-cbind.data.frame(nbar.m,nbap.m$value,nbap.m$value2) # adding the p value and its cut to the first dataset of R coefficients 
names(nbar.m)[5]<-paste("valuep") # change the column names of the dataframe 
names(nbar.m)[6]<-paste("signif.") 
nbar.m$row <- factor(nbar.m$row, levels=rev(unique(as.character(nbar.m$variable)))) # reorder the variable factor 
# Plotting the matrix correlation heatmap 
# Set options for a blank panel 
po.nopanel <-list(opts(panel.background=theme_blank(),panel.grid.minor=theme_blank(),panel.grid.major=theme_blank())) 
pa<-ggplot(nbar.m, aes(row, variable)) + 
geom_tile(aes(fill=value2),colour="white") + 
scale_fill_brewer(palette = "RdYlGn",name="Correlation")+ # RColorBrewer package 
opts(axis.text.x=theme_text(angle=-90))+ 
po.nopanel 
pa # check the first plot 
# Adding the significance level stars using geom_text 
pp<- pa + 
geom_text(aes(label=signif.),size=2,na.rm=TRUE) # you can play with the size 
# Workaround for the alpha aesthetics if it is good to represent significance level, the same workaround can be applied for size aesthetics in ggplot2 as well. Applying the alpha aesthetics to show significance is a little bit problematic, because we want the alpha to be low while the p value is high, and vice verse which can't be done without a workaround 
nbar.m$signif.<-rescale(as.numeric(nbar.m$signif.),to=c(0.1,0.9)) # I tried to use to=c(0.1,0.9) argument as you might expect, but to avoid problems with the next step of reciprocal values when dividing over one, this is needed for the alpha aesthetics as a workaround 
nbar.m$signif.<-as.factor(0.09/nbar.m$signif.) # the alpha now behaves as wanted except for the NAs values stil show as if with three stars level, how to fix that? 
# Adding the alpha aesthetics in geom_point in a shape of squares (you can improve here) 
pp<- pa + 
geom_point(data=nbar.m,aes(alpha=signif.),shape=22,size=5,colour="darkgreen",na.rm=TRUE,legend=FALSE) # you can remove this step, the result of this step is seen in one of the layers in the above green heatmap, the shape used is 22 which is again a square but the size you can play with it accordingly 

espero que esto puede ser un paso adelante para llegar allí! Tenga en cuenta:
- Algunos sugirieron clasificar o cortar el R^2 de manera diferente, está bien, podemos hacerlo por supuesto, pero aún queremos mostrarle a la audiencia GRÁFICAMENTE el nivel de significancia en lugar de preocupar al ojo con los niveles de las estrellas. ¿Podemos LOGRAR eso en principio o no?
- Algunos sugirieron que se redujeran los valores de p de forma diferente, Ok, esta puede ser una opción después de que no se muestren los 3 niveles de importancia sin molestar a la vista. Entonces podría ser mejor mostrar significativo/no significativo sin niveles
- Puede que haya una mejor idea que se te ocurra para la solución anterior en ggplot2 para la estética alfa y de tamaño, ¡esperamos tener noticias tuyas pronto!
- ¡La pregunta aún no ha sido respondida, esperando una solución innovadora! - ¡Curiosamente, el paquete "corrplot" lo hace! Este paquete me dio el siguiente gráfico, PD: los cuadrados cruzados no son significativos, nivel de signif = 0.05. ¿Pero cómo podemos traducir esto a ggplot2, podemos?

enter image description here

-O que puede hacer círculos y ocultar los que no significativa? cómo hacer esto en ggplot2 ?!
enter image description here

1

para significar importancia a lo largo de los coeficientes de correlación estimado que podría variar la cantidad de colorante - ya sea usando alpha o rellenando sólo un subconjunto de cada baldosa:

# install.packages("fdrtool") 
# install.packages("data.table") 
library(ggplot2) 
library(data.table) 

#download dataset 
nba <- as.matrix(read.csv("http://datasets.flowingdata.com/ppg2008.csv")[-1]) 
m <- ncol(nba) 
# compute corellation and p.values for all combinations of columns 
dt <- CJ(i=seq_len(m), j=seq_len(m))[i<j] 
dt[, c("p.value"):=(cor.test(nba[,i],nba[,j])$p.value), by=.(i,j)] 
dt[, c("corr"):=(cor(nba[,i],nba[,j])), by=.(i,j)] 

# estimate local false discovery rate 
dt[,lfdr:=fdrtool::fdrtool(p.value, statistic="pvalue")$lfdr] 

dt <- rbind(dt, setnames(copy(dt),c("i","j"),c("j","i")), data.table(i=seq_len(m),j=seq_len(m), corr=1, p.value=0, lfdr=0)) 


#use alpha 
ggplot(dt, aes(x=i,y=j, fill=corr, alpha=1-lfdr)) + 
    geom_tile()+ 
    scale_fill_distiller(palette = "RdYlGn", direction=1, limits=c(-1,1),name="Correlation") + 
    scale_x_continuous("variable", breaks = seq_len(m), labels = colnames(nba)) + 
    scale_y_continuous("variable", breaks = seq_len(m), labels = colnames(nba), trans="reverse") + 
    coord_fixed() + 
    theme(axis.text.x=element_text(angle=90, vjust=0.5), 
     panel.background=element_blank(), 
     panel.grid.minor=element_blank(), 
     panel.grid.major=element_blank(), 
) 

alpha

#use area 
ggplot(dt, aes(x=i,y=j, fill=corr, height=sqrt(1-lfdr), width=sqrt(1-lfdr))) + 
    geom_tile()+ 
    scale_fill_distiller(palette = "RdYlGn", direction=1, limits=c(-1,1),name="Correlation") + 
    scale_color_distiller(palette = "RdYlGn", direction=1, limits=c(-1,1),name="Correlation") + 
    scale_x_continuous("variable", breaks = seq_len(m), labels = colnames(nba)) + 
    scale_y_continuous("variable", breaks = seq_len(m), labels = colnames(nba), trans="reverse") + 
    coord_fixed() + 
    theme(axis.text.x=element_text(angle=90, vjust=0.5), 
     panel.background=element_blank(), 
     panel.grid.minor=element_blank(), 
     panel.grid.major=element_blank(), 
) 

area

K Aquí está la escala de los p.values: para obtener valores fáciles de interpretar que muestran una gran variación solo en regiones relevantes, utilizo estimaciones del límite superior para el falso descubrimiento local (lfdr) proporcionado por fdrtools. Es decir, el valor alfa de un mosaico es probablemente menor o igual a la probabilidad de que esa correlación sea diferente de 0.

Cuestiones relacionadas