Search code examples
rggplot2ggcorrplot

Correct placement of significant correlations when displaying upper or lower half of matrix


I am using ggcorrplot to visualize a correlation matrix. I want to remove non-significant correlation values but keep the color of the matrix cell. I can do this when showing the full matrix. However, the values are no longer displayed in the proper position if I show only the lower or upper portions of the matrix. How can I get the values to display properly when showing only one-half of the correlation matrix?

Similar SO question here.

library(ggplot2)
library(ggcorrplot)

# Make correlation coefficient matrix 
corr <- round(cor(mtcars),1)

# Make p-value matrix associated with the correlation coefficients
corr_p <- cor_pmat(mtcars)

# When full matrix is shown
ggcorrplot(corr, lab = FALSE, p.mat = corr_p, sig.level = 1) +
  geom_text(
  aes(x = Var2, y = Var1, label = round(value, 1)),
  \(d) subset(d, pvalue < 0.05))


# When only lower matrix is shown
ggcorrplot(corr, lab = FALSE, p.mat = corr_p, sig.level = 1, type = 'lower') +
  geom_text(
    aes(x = Var2, y = Var1, label = round(value, 1)),
    \(d) subset(d, pvalue < 0.05))


# When only upper matrix is shown
ggcorrplot(corr, lab = FALSE, p.mat = corr_p, sig.level = 1, type = 'upper') +
  geom_text(
    aes(x = Var2, y = Var1, label = round(value, 1)),
    \(d) subset(d, pvalue < 0.05))

Created on 2024-05-17 with reprex v2.1.0


Solution

  • EDIT : Here's another option to fulfill the needs of the OP :

    ### Packages
    library(ggplot2)
    library(ggcorrplot)
    library(dplyr)
    
    ### Make correlation coefficient matrix 
    corr <- round(cor(mtcars),1)
    
    ### Make p-value matrix associated with the correlation coefficients
    corr_p <- cor_pmat(mtcars)
    
    ### Create and store the graph
    k=ggcorrplot(corr, lab = FALSE, p.mat = corr_p, sig.level = 1) +
      geom_text(
        aes(x = Var2, y = Var1, label = round(value, 1)),
        \(d) subset(d, pvalue < 0.05))
    
    ### Store the graph into a ggplot object you can modify
    modify=ggplot_build(k)
    
    ### Transform the ggplot object
    ### First, we remove the data related to the upper part of the graph
    modify$data[[3]]=modify$data[[3]] %>%
      as_tibble() %>%
      mutate(up_low=case_when(y>x~"haut",
                              y<x~"bas",.default = "cor"),.before = 1) %>%
      filter(up_low=="bas") %>% 
      select(-up_low) %>% 
      as.data.frame()
    
    ### Then, we colour the upper part and the correlation diagonal in white
    modify$data[[1]]=modify$data[[1]]%>%
      as_tibble() %>%
      mutate(up_low=case_when(y>x~"haut",
                              y<x~"bas",.default = "cor"),.before = 1) %>% 
      mutate(fill=case_when(up_low=="cor"~"#FFFFFF",
                            up_low=="haut"~"#FFFFFF",.default = fill)) %>% 
      select(-up_low) %>% 
      as.data.frame()
    
    ### We export the result with ggplot_table and display it properly with grid 
    grid::grid.newpage()
    grid::grid.draw(ggplot_gtable(modify))
    

    Output :

    Fix


    Original answer :

    A possible workaround is to replace values in your p-values matrix :

    library(ggplot2)
    library(ggcorrplot)
    library(purrr)
    
    # Make correlation coefficient matrix 
    corr <- round(cor(mtcars),1)
    
    # Make p-value matrix associated with the correlation coefficients
    corr_p <- cor_pmat(mtcars)
    
    ### Modify the corr_p matrix
    ### p-values of the lower portion will be replaced by 1
    f=dim(corr_p)[1]
    walk(.x = 1:(f-1),.f = ~{corr_p[(.x+1):f,.x]<<-1})
    
    ### Create the graph
    ggcorrplot(corr, lab = FALSE, p.mat = corr_p, sig.level = 1) +
      geom_text(
        aes(x = Var2, y = Var1, label = round(value, 1)),
        \(d) subset(d, pvalue < 0.05))
    

    Output :

    RG