Home > Back-end >  Control Label of Contour Lines in `contour()`
Control Label of Contour Lines in `contour()`

Time:10-05

I am using image() and contour() to create a "heatmap" of probabilities - for example:

enter image description here

I was asked to change the labels such that they "do not overlap the lines, and the lines are unbroken." After consulting ?contour(), I tried changing to method = "edge" and method = "simple", but both fail print the labels (although the lines are unbroken), and cant seem to find posts regarding similar issues elsewhere.

enter image description here

Any advice on how to manipulate the labels to appear adjacent to (not on top of) unbroken lines would be much appreciated. I would prefer base R but also would welcome options from more flexible packages or alternative base R functions.

Minimal code to recreate example figure is here:

# Generate Data
Rs <- seq(0.02, 1.0, 0.005)
ks <-  10 ^ seq(-2.3, 0.5, 0.005) 
prob <- function(Y,R,k) { 
  exp(lgamma(k*Y Y-1) - lgamma(k*Y) - lgamma(Y 1)   (Y-1) * log(R/k) - (k*Y Y-1) * log(1 R/k))
}
P05 <- matrix(NA, ncol = length(ks), nrow = length(Rs))
for(i in 1:length(Rs)) {
  for(j in 1:length(ks)) {
    P05[i,j] <- 1 - sum(prob(1:(5 - 1), Rs[i], ks[j]))
  }
}
colfunc <- colorRampPalette(c("grey25", "grey90"))
lbreaks <- c(-1e-10, 1e-5, 1e-3, 5e-3, 1e-2, 2e-2, 5e-2, 1e-1, 1.5e-1, 1)

## Create Figure
image(Rs, ks, P05,
      log="y", col = rev(colfunc(length(lbreaks)-1)), breaks = lbreaks, zlim = lbreaks,
      ylim = c(min(ks), 2), xlim = c(0,1))
contour(Rs, ks, P05, levels = lbreaks, labcex = 1, add = TRUE)

CodePudding user response:

There is an easy(ish) way to do this in ggplot, using the geomtextpath package.

First, convert your matrix to an x, y, z data frame:

df <- expand.grid(Rs = Rs, ks = ks)
df$z <- c(P05)

Now plot a filled contour, and then geom_textcontour. By default the text will break the lines, as in contour, but if you set the vjust above one or below zero the lines will close up as they don't need to break for the text.

I've added a few theme and scale elements to match the aesthetic of the base graphics function. Note the text and line size, color etc remain independently adjustable.

library(geomtextpath)

ggplot(df, aes(Rs, ks, z = z))  
  geom_contour_filled(breaks = lbreaks)  
  geom_textcontour(breaks = lbreaks, color = 'black', size = 5,
                   aes(label = stat(level)), vjust = 1.2)  
  scale_y_log10(breaks = c(0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2), 
                expand = c(0, 0))  
  scale_fill_manual(values = rev(colfunc(9)), guide = 'none')  
  scale_x_continuous(expand = c(0, 0))  
  theme_classic(base_size = 16)  
  theme(axis.text.y = element_text(angle = 90, hjust = 0.5),
        axis.ticks.length.y = unit(3, 'mm'),
        plot.margin = margin(20, 20, 20, 20))

enter image description here

CodePudding user response:

The contour function is mostly written in C, and as far as I can see, it doesn't support the kinds of labels you want.

So I think there are two ways to do this, neither of which is very appealing:

  1. Modify the source to the function. You can see the start of the labelling code here. I think you would need to rebuild R to incorporate your changes; it's not easy to move a function from a base package to a contributed package.

  2. Draw the plot with no labels, and add them manually after the fact. You could add them using text(), or produce an output file and use an external program to edit the output file.

  • Related