How to auto adjust R figure axis labels to matrix

2019-05-23 22:58发布

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

2条回答
beautiful°
2楼-- · 2019-05-23 23:14

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

查看更多
一纸荒年 Trace。
3楼-- · 2019-05-23 23:20

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

查看更多
登录 后发表回答