2

I want to make the fontsize of the y-axis labels adjustable to the input data size on the y-axis like in Fig. 3, in contrast to the current situation in Fig. 1-2 where labels are not next to the corresponding lines. Code

library("corrgram")

# https://stackoverflow.com/a/40387233/54964
ids <- seq(1,18)
x_at <- seq(0.075, 0.925, length.out = length(ids))
y_at <- seq(0.075, 0.91, length.out = length(ids))

createLabels <- function(xlab, ylab, x_labels, y_labels){
ids <- y_labels # assume here
x_at <- seq(0.075, 0.925, length.out = length(ids))
y_at <- seq(0.075, 0.91, length.out = length(ids))
mtext(xlab, side = 1, line = 4)
mtext(ylab, side = 2, line = 3)
axis(1, at=x_at, labels=x_labels, line = 1.5, tick=F, cex.axis=.7)
axis(2, at=y_at, labels=y_labels, line = 1, tick=F, cex.axis=.7, las=1) # horizontal y-axis labels; rawr
}

corrgram(baseball,main="Baseball data PC2/PC1 order")
createLabels(xlab="Patient 1 ID", ylab="Patient 2 ID", x_labels=ids, y_labels=ids)

Fig. 1 Output with the limited test data baseball, Fig. 2 Output with the real case, Fig. 3 Expected output

enter image description here enter image description here enter image description here

Expected output: automatically adjustable label font size to the input data size on the y-axis; example of the output created by makeMatrixPlot(list, ids, title) found here in Fig. 3

Testing Istrel's answer with big data set where long IDs

Complete code here which visualises correctly but gives backside strange outputs an NULLs, here some key points about optimised parameters

# https://stackoverflow.com/a/40485734/54964
cex_lab<-0.9 # little smaller fontsize for matrix >= 20x20
oma<-c(4, 4, 6, 4)
gap<-0
las<-2 # both axis labels always perpendicular

Output complications as the warning and many NULLs

In max(l.wid) : no non-missing arguments to max; returning -Inf
[[1]]
[[1]][[1]]
NULL
...
[[1]][[7]]
NULL


[[2]]
[[2]][[1]]
NULL
...    
[[2]][[7]]
NULL


[[3]]
[[3]][[1]]
NULL
...  
[[3]][[7]]
NULL

Call it for instance by

library("corrplot")
library("psych")

ids <- seq(1,11) 

M.cor <- cor(mtcars)
colnames(M.cor) <- ids
rownames(M.cor) <- ids

p.mat <- psych::corr.test(M.cor, adjust = "none", ci = F)
p.mat <- p.mat[["r"]]

corrplot(M.cor, 
  method = "color", 
  type = "upper", 
  tl.col = 'black', 
  diag = TRUE, 
  p.mat = p.mat, 
  sig.level = 0.0000005
)

createLabels(xlab="Patient 1 ID", ylab="Patient 2 ID and Ages", x_labels=ids, y_labels="") 

R: 3.3.1
Used graphic objects: corrplot, corrgram, ...
OS: Debian 8.5

Community
  • 1
  • 1
Léo Léopold Hertz 준영
  • 134,464
  • 179
  • 445
  • 697

2 Answers2

2

Corrgram uses mfrow from par() for squares drawing. We can use that for labeling. The number of labels should be equal to the number of columns in the matrix. If you set oma or gap arguments in corrgram function, you have to specify same parameters in createLabels function.

BTW, if you use corrgram without main argument, you will need oma=c(4,4,4,4) in createLabels

createLabels <- function(xlab, ylab, x_labels, y_labels, 
                cex_lab=1.3, oma=c(4, 4, 6, 4), gap=0, las=0){
# oma and gap args same as in corrgram
nc <- length(x_labels) # get number of columns

# Inititate mfrow partition as in corrgram
opar <- par(mfrow = c(nc, nc), mar = rep.int(gap/2, 4), oma = oma) #save old par parameters

# Create matrix of outer cells indexes and positions
left_side <- matrix(c(nc:1, rep(1, nc), rep(2, nc)), nc)
bottom_side <- matrix(c(rep(nc, nc), 1:nc, rep(1, nc)), nc)
sides <- rbind(left_side, bottom_side)


# Dublicate labels vector
labels <- c(y_labels, x_labels)

# Loop over each outer cell
for (i in c(1:(nc*2))){
    cell_ind <- sides[i, ]
    par(mfg=c(cell_ind[1], cell_ind[2], nc, nc)) # set current plotting cell
    usr<-par("usr")
    clip(usr[1], -2, usr[3], usr[4]) # alter clipping region
    axis(cell_ind[3], at=0.5, labels=labels[i], 
        outer=TRUE, xpd=NA, lwd=NA, mgp=c(3,0,0.2), cex.axis=cex_lab, las=las)
}

# Add labels
par(opar)
mtext(xlab, side = 1, line = -1.5, outer=TRUE, xpd=NA)
mtext(ylab, side = 2, line = -1.5, outer=TRUE, xpd=NA)
}

corrgram(baseball,main="Baseball data PC2/PC1 order")
createLabels(xlab="Patient 1 ID", ylab="Patient 2 ID", 1:18, 1:18)

enter image description here enter image description here

Léo Léopold Hertz 준영
  • 134,464
  • 179
  • 445
  • 697
Istrel
  • 2,508
  • 16
  • 22
  • 1
    `1:18` is an argument of a function. i.e. `createLabels("X-lab", "Y-lab", x_labels=c(1:18))`. So you can specify any vector of names, while its length is equal to data size. What if you will need names like c("a", "b", "c") – Istrel Nov 08 '16 at 12:44
  • 1
    I have added y_labels. Try it now. Of course, you can move those arguments as hard-coded variables. – Istrel Nov 08 '16 at 12:58
  • 1
    Try `las=2`, i.e. always perpendicular. As for font size, it is `cex_lab` argument, try to change it. – Istrel Nov 08 '16 at 13:22
  • Initially, you asked about `corrgram`. Now you say that you have a problem with `corrplot`. – Istrel Nov 14 '16 at 10:31
  • Also, for my function you need labels vectors of length exactly equal to data dimensions. I.e. for your example `x_labels` AND `y_labels` should be of length 11 (in your snippet, the length of `y_labels` is equal to 1). – Istrel Nov 14 '16 at 10:37
  • And what that `ages` variable is? – Istrel Nov 14 '16 at 10:39
  • Try `y_labels=rep("", 11)` to make a vector of 11 `""`. – Istrel Nov 14 '16 at 11:44
1

The corrgram package has been updated (version 1.11) with better support for labels along the axes. I've used the basic idea from Leo and added it to the package. For example:

require(corrgram)
labs=colnames(state.x77)
corrgram(state.x77, oma=c(7, 7, 2, 2),
         outer.labels=list(bottom=list(labels=labs,cex=1.5,srt=60),
                           left=list(labels=labs,cex=1.5,srt=30)))
mtext("Bottom", side=1, cex=2, line = -1.5, outer=TRUE, xpd=NA)
mtext("Left", side=2, cex=2, line = -1.5, outer=TRUE, xpd=NA)

corrgram

Kevin Wright
  • 2,397
  • 22
  • 29