Jacek Mucha
Jacek Mucha

Reputation: 71

Is there fast way to present Pearson correlation on the upper panel and Spearman correlation on the lower panel?

The library corrgram gives an opportunity to draw elegant correlograms. However, there is no easy way in the documentation to obtain both Spearman and Pearson correlations on the same graph.

Perhaps computing a correlation matrices for both coefficients and paste them would be an option, but it does not seem to be the proper way.

I think the image will explain properly what I want to get :

I want to get:

cors <- cor(state.x77, method = "pearson")
corsSp <- cor(state.x77, method = "spearman")
for(i in 1:nrow(cors))
{
for(j in i:ncol(cors))
{
cors[i,j] <- corsSp[i,j]
m[i,j] <- j
}
}
corrgram(cors, type = "corr")

in a more elegant way.

Upvotes: 3

Views: 234

Answers (3)

Marco Sandri
Marco Sandri

Reputation: 24262

A different way to calculate your correlation matrix:

mycor <- Vectorize(function(i, j) {
   method <- ifelse(i>j, "pearson", "spearman")
   cor(state.x77[,i], state.x77[,j], method = method)
})
sqn <- 1:ncol(state.x77)
cors <- outer(sqn, sqn, FUN=mycor)

Upvotes: 1

ophdlv
ophdlv

Reputation: 254

Taking for example these data:

df = data.frame(x = runif(100),
                y = runif(100),
                z = runif(100),
                w = runif(100),
                v = runif(100),
                u = runif(100))

Computing the correlation matrix:

library("dplyr")
mat = matrix(NA, nrow = ncol(df), ncol = ncol(df)) %>%
  `row.names<-`(names(df)) %>%
  `colnames<-`(names(df))


mat[upper.tri(mat)] = cor(df,method="pearson")[upper.tri(mat)]
mat[lower.tri(mat)] = cor(df,method="spearman")[lower.tri(mat)]

Converting from long to wide format:

cor.long = reshape2::melt(mat)

Then plot:

library("ggplot2")
library("RColorBrewer")

pal = colorRampPalette(rev(brewer.pal(11, "Spectral")))

ggplot(cor.long, aes(Var1, factor(Var2, rev(levels(Var2))), fill = value)) +
  geom_tile() +
  geom_text(aes(label = Var1), data = cor.long %>% filter(Var1 == Var2)) + 
  geom_text(aes(label = value %>% round(digits = 3)), data = cor.long %>% filter(Var1 != Var2)) + 
  scale_y_discrete(limits = rev(levels(df$Var2))) +
  scale_fill_gradientn(colours = pal(100), na.value  = "white", limits=c(-.5,.5)) +
  theme(panel.background = element_blank(),
        axis.title = element_blank(),
        axis.text = element_text(angle = 45),
        legend.position = "none")

enter image description here

Upvotes: 2

thothal
thothal

Reputation: 20369

You can try to rebuild your graph by hand via ggplot which gives pretty similiar results (except the patterned background):

library(ggplot2)
library(tibble)
library(dplyr)
library(tidyr)

## transform the cor matrix (with pearons and spearmann coeeficients) 
cor_cleaned <- cors %>%
  as.data.frame() %>%
  rownames_to_column("x") %>%
  as_tibble() %>%
  gather(y, cor, -x) %>%
  mutate(x   = factor(x, unique(x)),
         y   = factor(y, rev(levels(x))),
         dir = factor(sign(cor)))

cor_tri <- cor_cleaned %>%
  filter(x != y)

cor_diag <- cor_cleaned %>%
  filter(x == y)

ggplot(cor_tri, aes(x, y, alpha = abs(cor), fill = dir)) +
  geom_tile(show.legend = FALSE, color = "gray") +
  geom_tile(show.legend = FALSE, color = "gray", fill = NA, data = cor_diag) +
  geom_text(aes(label = y), data = cor_diag, show.legend = FALSE) + 
  scale_fill_manual(values = c("1" = "navy", "-1" = "red")) +
  theme_minimal() +
  theme(panel.grid = element_blank(),
        axis.text  = element_blank(),
        axis.title = element_blank())

Corrgram with ggplot

Upvotes: 2

Related Questions