Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

False positive vs. false negative trade off plot

I'm working on a decision making analysis where I'm trying to illustrate the trade off between false positive (false go) vs. false negative (false no-go) using R. I have created a density plot with null and alternative hypothesis curves, but would like to further illustrate the relationship via the example plots like these. Would appreciate the help in creating plots like example 1 and 2, especially example 1. Thank you!

Density plot

my density plot

Example 1

example 1

Example 2

example 2

like image 984
user2272972 Avatar asked Jun 11 '26 12:06

user2272972


1 Answers

I used two offset normal distributions, the premise carries into whatever curves you can imagine.

library(ggplot2)

xs <- seq(-2, 4, length.out = 201)
dat <- do.call(rbind,
  list(data.frame(x=xs, y=dnorm(xs), id="1"),
       data.frame(x=xs, y=dnorm(xs, 2), id="2")))

plot 1

vline <- 1
eps <- 1e-3

ggplot(dat, aes(x, y, group = id, color = id)) +
  geom_line() +
  geom_area(aes(fill = id),
            data = ~ subset(., (id == "1" & x > (vline+eps)) | (id == "2" & x < (vline-eps)))) +
  geom_vline(xintercept = vline, linetype = "dashed") +
  labs(x = "Hazard Ratio", y = NULL) +
  guides(color = "none", fill = "none") +
  theme_classic() +
  theme(
    axis.line.y = element_blank(),
    axis.text.y = element_blank(),
    axis.ticks.y = element_blank()
  )

enter image description here

The vline is the differentiating line here, if it is not at the intersection then it can still be useful. For instance,

vline <- 1.2

enter image description here

plot 2

rng <- c(0.75, 0.85)
rngdat <- do.call(rbind,
  by(dat, dat$id, function(z) with(z, data.frame(approx(x, y, xout = rng), id = id[1]))))
rngdat$otherx <- fifelse(rngdat$id == "1", Inf, -Inf)

ggplot(dat, aes(x, y, group = id, color = id)) +
  geom_line(na.rm = TRUE) +
  geom_segment(aes(xend = x, yend = 0),
               data = subset(rngdat, id == 1),
               color = "black", linetype = "dashed") +
  geom_segment(aes(xend = otherx, yend = y),
               data = rngdat, linetype = "dashed") +
  coord_cartesian(xlim = c(0, 2)) +
  scale_x_continuous(name = "HR gate") +
  scale_y_continuous(
    name = "False Go Probability",
    sec.axis = sec_axis(~ ., name = "False No-Go Probability")) +
  scale_color_manual(values = c("1" = "blue", "2" = "red")) +
  guides(color = "none") +
  theme_classic() +
  theme(
    axis.line.y.left = element_line(color = "red"),
    axis.line.y.right = element_line(color = "blue")
  )

enter image description here

plot 3

offset <- max(rngdat$y[rngdat$id == "1"]) + 0.1
cutoff <- 0
dat <- transform(
  dat,
  yoff = ifelse(id == "1", 0.05 + offset, 0),
  cat = ifelse(id == "1",
               ifelse(x < cutoff, "True Positive", "False Negative"),
               ifelse(x < cutoff, "False Positive", "True Negative")))

ggplot(dat, aes(x, y = y + yoff)) +
  geom_ribbon(aes(ymin = yoff, ymax = y + yoff,
                  group = cat, fill = cat, alpha = cat),
              na.rm = TRUE) +
  geom_vline(xintercept = cutoff) +
  scale_fill_manual(
    name = NULL,
    values = c("True Positive" = "red", "False Negative" = "red",
               "False Positive" = "blue", "True Negative" = "blue")) +
  scale_alpha_manual(
    name = NULL,
    values = c("True Positive" = 1, "False Negative" = 0.2,
               "False Positive" = 0.2, "True Negative" = 1)) +
  labs(x = NULL, y = NULL) +
  theme(
    legend.position = "bottom",
    axis.text.y = element_blank(),
    axis.ticks.y = element_blank()
  )

enter image description here

like image 153
r2evans Avatar answered Jun 13 '26 17:06

r2evans



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!