Especially when you´re starting a SEM-analysis you should have a look at your observed variables and the correlations between them. As usual with R, there´s an app a package for that. It´s called corrplot and seems to rely on base R graphics.
library("corrplot") data(mtcars) M <- cor(mtcars) ## different color scale and methods to display corr-matrix corrplot(M, method="number", col="black", cl.pos="n")
Pretty basic, huh? If you would rather have a good looking table, try the mighty sjPlot-package. It uses spearman-correlation as default.
sjPlot::sjt.corr(mtcars, pvaluesAsNumbers=FALSE, triangle="lower", stringDiagonal=c(1,1,1,1,1,1,1,1,1,1), CSS=list(css.thead="border-top:double black; font-weight:normal; font-size:0.9em;", css.firsttablecol="font-weight:normal; font-size:0.9em;"))
Also thanks to the sjPlot-package from Daniel Lüdecke you only need this code:
sjp.corr(mtcars)
As usual, i´ve had my own thoughts on how a perfect correlation matrix for my sociological survey-data should look like. This was my idea: In the lower triangle it contains a jittered scatterplot of the responses. A scatterplot of rating-items with 5 categories does not work without jitter. Diagonally are the univariate distributions of the items as barplot, with one bar for each category. In the upper triangle you find the correlation (spearman) and p-value.
library("ggplot2") library("plyr") library("dplyr") library("gtable") library("sjPlot") #pass the items as a dataframe to the function dat<- yourdata %>% select(youritem1,youritem2...) #------------ # Number of items, generate labels, and set size of text for correlations and item labels n <- dim(dat)[2] labels <- paste0("Item ", 1:n) sizeItem = 16 sizeCor = 4 ## List of scatterplots scatter <- list() for (i in 2:n) { for (j in 1:(i-1)) { # Data frame df.point <- na.omit(data.frame(cbind(x = dat[ , j], y = dat[ , i]))) # Plot p <- ggplot(df.point, aes(x, y)) + geom_jitter(size = .7, position = position_jitter(width = .2, height= .2)) + stat_smooth(method="lm", colour="black") + theme_bw() + theme(panel.grid = element_blank()) name <- paste0("Item", j, i) scatter[[name]] <- p } } ## List of bar plots bar <- list() for(i in 1:n) { # Data frame bar.df <- as.data.frame(table(dat[ , i], useNA = "no")) names(bar.df) <- c("x", "y") # Plot p <- ggplot(bar.df) + geom_bar(aes(x = x, y = y), stat = "identity", width = 0.6) + theme_bw() + theme(panel.grid = element_blank()) + ylim(0, max(bar.df$y*1.05)) name <- paste0("Item", i) bar[[name]] <- p } ## List of tiles tile <- list() for (i in 1:(n-1)) { for (j in (i+1):n) { # Data frame df.point <- na.omit(data.frame(cbind(x = dat[ , j], y = dat[ , i]))) # na.omit returns the object with incomplete cases removed x = df.point[, 1] y = df.point[, 2] correlation = cor.test(x, y,method="spearman",use="pairwise") #unter getOption("na.action") nachsehen ==> na.action = na.omit cor <- data.frame(estimate = correlation$estimate, statistic = correlation$statistic, p.value = correlation$p.value) cor$cor = paste0("r = ", sprintf("%.2f", cor$estimate), "\n", # "t = ", sprintf("%.2f", cor$statistic), "\n", "p = ", sprintf("%.3f", cor$p.value)) # Plot p <- ggplot(cor, aes(x = 1, y = 1)) + geom_tile(aes(fill = estimate)) + geom_text(aes(x = 1, y = 1, label = cor), colour = "White", size = sizeCor, show_guide = FALSE) + theme_bw() + theme(panel.grid = element_blank()) + scale_fill_gradient2(limits = c(-1,1), midpoint=0,low=("black"),mid="grey",high=("black")) #Neu hinzugefügt name <- paste0("Item", j, i) tile[[name]] <- p } } # Convert the ggplots to grobs, # and select only the plot panels barGrob <- llply(bar, ggplotGrob) barGrob <- llply(barGrob, gtable_filter, "panel") scatterGrob <- llply(scatter, ggplotGrob) scatterGrob <- llply(scatterGrob, gtable_filter, "panel") tileGrob <- llply(tile, ggplotGrob) tileGrob <- llply(tileGrob, gtable_filter, "panel") ## Set up the gtable layout gt <- gtable(unit(rep(1, n), "null"), unit(rep(1, n), "null")) ## Add the plots to the layout # Bar plots along the diagonal for(i in 1:n) { gt <- gtable_add_grob(gt, barGrob[[i]], t=i, l=i) } # Scatterplots in the lower half k <- 1 for (i in 2:n) { for (j in 1:(i-1)) { gt <- gtable_add_grob(gt, scatterGrob[[k]], t=i, l=j) k <- k+1 } } # Tiles in the upper half k <- 1 for (i in 1:(n-1)) { for (j in (i+1):n) { gt <- gtable_add_grob(gt, tileGrob[[k]], t=i, l=j) k <- k+1 } } # Add item labels gt <- gtable_add_cols(gt, unit(1.5, "lines"), 0) gt <- gtable_add_rows(gt, unit(1.5, "lines"), 2*n) for(i in 1:n) { textGrob <- textGrob(labels[i], gp = gpar(fontsize = sizeItem)) gt <- gtable_add_grob(gt, textGrob, t=n+1, l=i+1) } for(i in 1:n) { textGrob <- textGrob(labels[i], rot = 90, gp = gpar(fontsize = sizeItem)) gt <- gtable_add_grob(gt, textGrob, t=i, l=1) } # Add small gap between the panels for(i in n:1) gt <- gtable_add_cols(gt, unit(0.2, "lines"), i) for(i in (n-1):1) gt <- gtable_add_rows(gt, unit(0.2, "lines"), i) # Add chart title gt <- gtable_add_rows(gt, unit(1.5, "lines"), 0) textGrob <- textGrob("Korrelationsmatrix", gp = gpar(fontface = "bold", fontsize = 16)) gt <- gtable_add_grob(gt, textGrob, t=1, l=3, r=2*n+1) # Add margins to the whole plot for(i in c(2*n+1, 0)) { gt <- gtable_add_cols(gt, unit(.75, "lines"), i) gt <- gtable_add_rows(gt, unit(.75, "lines"), i) } # Draw it grid.newpage() grid.draw(gt)
Kudos to Stackoverflow User Sany Muspratt for helping me to figure this out.
And here it is in its full beauty (and grey for cheaper printing):