How to have axis labels in R corrgram?

2019-02-20 00:07发布

问题:

I would like to have horizontal and vertical labels on x-axis and y-axis, see the following pseudocode. Henrik's comment of the related thread 2013 is about turning off diagonal labels and then trying to associate labels for the axes, but I do not want to turn off the diagonal labels

You may turn the diagonal labels off by setting labels = NULL. Then you can try to add your labels where you wish by using text

library("corrgram")
ids <- c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18)
# https://cran.r-project.org/web/packages/corrgram/vignettes/corrgram_examples.html
corrgram(baseball,main="Baseball data PC2/PC1 order") +
          xlab("Patient 1 ID") +
          ylab("Patient 2 ID") +
          scale_x_discrete(labels = ids) +
          scale_y_discrete(labels = ids)

Fig. 1 test data

Testing JayT's proposal

It would be nice to overload the first parameter place with all possible parameters and then have only one extra paremeter ids in the new function; pseudocode

# https://stackoverflow.com/a/40387233/54964
corrgramLabels <- function(x, ids){
        corrgram(x=x)
        mtext("Patient 1 ID", side = 1, line = 4)
        mtext("Patient 2 ID", side = 2, line = 3)
        x_at <- seq(0.075, 0.925, length.out = length(ids))
        y_at <- seq(0.075, 0.91, length.out = length(ids))
        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)
}

Attempt to use it but the following error

corrgramLabels(M,
  upper.panel=panel.pie,
  lower.panel=panel.shade,
  text.panel=panel.txt,
  order=NULL,
  diag.panel=panel.minmax,
  main=title)

Error

Error in corrgramLabels(M, upper.panel = panel.pie, lower.panel = panel.shade,  : 
  unused arguments (upper.panel = panel.pie, lower.panel = panel.shade, text.panel = panel.txt, order = NULL, diag.panel = panel.minmax, main = title)
Execution halted

Proposal for the solution

I actually think that the best solution would be a function independent of corrgram. Start a function createLabels() after corrgram() and you get the result. Is that possible?

OS: Debian 8.5
R: 3.3.1
Related: Corrgram Package Horizontal and Vertical Labels

回答1:

For the axes you can use mtext (m for margin region; text will not work):

library("corrgram")
ids <- seq(1, 18)
corrgram(baseball,main="Baseball data PC2/PC1 order")

mtext("Patient 1 ID", side = 1, line = 4)
mtext("Patient 2 ID", side = 2, line = 3)

You can use the line parameter to increase or decrease the distance to the actual plot.

The labels are more difficult. You could do it with mtext or axis, but if you resize the figure, it won't fit with the rest. So this is not really optimal. If you know how large your figure will be, it should still work; for example 800x800 pixels, optimize the position (at parameter):

axis(1, at=seq(0.09, 0.91, length.out = length(ids)),
     labels=as.character(ids), line = 1.5, tick=F, cex.axis=.7)
axis(2, at=seq(0.08, 0.88, length.out = length(ids)),
     labels=as.character(ids), line = 1, tick=F, cex.axis=.7)

Figure output: Test data with axes and labels

For a better solution, you might need to look inside the function and find out how and where exactly the boxes are drawn.

Edit after comment by Masi: Of course we can build a function around that:

corrgramMasi <- function(x, main, xlab, ylab, x_labels, y_labels, x_at, y_at){
  corrgram(x=x, main=main)
  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)
}

Illustration to use the function with adjusted "at" parameter values to save the figure with a resolution of 800x800 pixels:

x_at <- seq(0.075, 0.925, length.out = length(ids))
y_at <- seq(0.075, 0.91, length.out = length(ids))
png("corrgramMasi.png", width=800, height=800)
  corrgramMasi(baseball, "Baseball data PC2/PC1 order", xlab="Patient 1 ID",
               ylab="Patient 2 ID", x_labels=ids, y_labels=ids, x_at=x_at, y_at=y_at)
dev.off()

And if you have several corrgrams, you could just use Map and change parameters specifically. In this case I simply use the baseball data set two times and change the title, but leave all other variables constant:

Map(corrgramMasi, x=list(baseball, baseball), main=list("title 1", "title 2"), 
    xlab="Patient 1 ID", ylab="Patient 2 ID", x_labels=ids, y_labels=ids,
    x_at=x_at, y_at=y_at)

If you have 10 corrgrams, then just put the data into the x list and change the titles (or set them to a constant value as well). If you want to change another value (e.g. xlab) you will have to use a list with the corresponding values, e.g. xlab=list("xlab for corrgram 1", "xlab for corrgram 2", ...).

But as said earlier, the "at" parameter is kind of dirty here, so this is certainly not the best solution.

Edit 2: As suggested by Masi it is probably better to use a separate function for creating the labels:

createLabels <- function(xlab, ylab, x_labels, y_labels, x_at, y_at){
  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)
}

Then call createLabels after making the corrgram:

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


标签: r labels