2

I have been trying to make a contour plot for prediction models with R, based on the bplot function in "rms" package. The codes are as follows:

library(rms)
n <- 1000
set.seed(17)
age <- rnorm(n, 50, 10)
blood.pressure <- rnorm(n, 120, 15)
cholesterol <- rnorm(n, 200, 25)
sex <- factor(sample(c('female','male'), n,TRUE))
L <- .4*(sex=='male') + .045*(age-50) + (log(cholesterol - 10)-5.2)*(-2*(sex=='female') + 2*(sex=='male'))
y <- ifelse(runif(n) < plogis(L), 1, 0)
ddist <- datadist(age, blood.pressure, cholesterol, sex)
options(datadist='ddist')
fit <- lrm(y ~ blood.pressure + sex * (age + rcs(cholesterol,4)), x=TRUE, y=TRUE)
p <- Predict(fit, age, cholesterol, sex, np=50)
bplot(p,, contourplot, region = TRUE,col.regions=topo.colors)

And I noticed that the output figure was like this:

enter image description here

I couldn't find out how to smoothen the zigzag borderlines between two filled regions, so I wonder if this kind of contour plot for prediction models could be made with ggplot2 or if there are any other solutions to smoothen the zigzag borderlines.

pogibas
  • 27,303
  • 19
  • 84
  • 117
Hans Wang
  • 25
  • 3

1 Answers1

0

You can plot similar plot with combination of geom_tile and geom_contour.

library(ggplot2)
ggplot(data.frame(p), aes(age, cholesterol, fill = yhat, z = yhat)) +
    geom_tile() +
    geom_contour(color = "black") +
    scale_fill_distiller(palette = "Spectral", limits = c(-2, 2)) +
    labs(x = "Age",
         y = expression(Total~Cholesterol["mg/dl"]),
         fill = NULL) +
    facet_grid(~ sex) +
    theme_classic()

enter image description here

Edit: As OP requested I added discrete colors:

ggplot(data.frame(p), aes(age, cholesterol, z = yhat)) +
    geom_tile(aes(fill = factor(round(yhat)))) +
    geom_contour(color = "black") +
    labs(x = "Age",
         y = expression(Total~Cholesterol["mg/dl"]),
         fill = NULL) +
    facet_grid(~ sex) +
    theme_classic()
pogibas
  • 27,303
  • 19
  • 84
  • 117
  • Thanks a lot! This figure looks much better than mine! Is there any method that can fill the regions between 2 contour lines with only one color instead of gradient color in this figure? For example, is it possible to fill in the region between 0 and 0.5 with green and that between 0.5 and 1 with yellow? – Hans Wang Feb 12 '18 at 11:54
  • @HansWang I added solution, however it gives pixeled figure (it's not probably what you want to do; don't know if that's even possible). Please let me know if it works/how can I improve my answer. – pogibas Feb 12 '18 at 12:23
  • Thanks again! I tried this new code, and similarly I got pixeled figure. I thought this might be related to the number of cases in the data frame (perhaps the size of the pixels are decided by the number of cases), and I created a data set with 5000 thousand cases instead of the original 1000, but still it didn't help. – Hans Wang Feb 12 '18 at 12:36
  • @HansWang It's just not possible - either you: 1. Have continuous color/fill scale; 2. Have discrete scale, but pixeled; 3. Have discrete scale, but step-line contour line (actually I don't know you to draw such line). – pogibas Feb 12 '18 at 12:40
  • 1
    Thanks, it's probably just a disadvantage of rms package, I'll try some other packages. – Hans Wang Feb 14 '18 at 08:15