How to add individual pre-calculated h-lines to a plot in ggplot?

30 views Asked by At

I've created a plot and need to add a threshold line to it:

plot showing hline depicting threshold

BlinkRep <- ggplot(data = BlinkRes, aes(x = well, y = FluoCont, fill = Validity))+
  geom_point(position = position_jitter(), shape = 21)+
  scale_fill_manual(values = scalecols1,
                    breaks = scalebreaks1,
                    labels = scalelabs1)+
  ylab("Fluorescence Signal")+
  xlab("Well")+
  theme_light()+
  theme(axis.title.y = element_text(size = 16, family = "sans"), 
        legend.text = element_text(size = 16, family = "sans"),
        axis.text.x = element_text(colour ="black", size = 16, family = "sans"),
        axis.text.y = element_text(colour ="black", size = 16, family = "sans"),
        axis.title.x = element_text(colour = "black", size = 16, family = "sans"),
        legend.title = element_text(size = 16, family = "sans"),
        panel.background = element_blank(),
        axis.line = element_line(colour = "black"),
        plot.title = element_text(size = 10, hjust = 0.5))+
  geom_hline(yintercept = univthreshold, colour ="red", linetype="dashed", linewidth = 1)+
  guides(fill=guide_legend(title="Bead Validity"))
BlinkRep
ggsave("Results/RepResults.png", plot = BlinkRep, dpi = 500, height = 7, units = "in", width = 14)

Currently the threshold I have added is an average that I have calculated from all the wells, however each well has its own threshold. The thresholds are in a separate dataframe:

> head(repthresh)
    WGR Bead.Type      Bead.Type.Name Well Channel   Analyte Lambda..cp.Bead. Lambda.95..CI..cp.Bead. Copies.in.Sample..cp.
2 WGR_1         1 Analyte_1_Analyte_2   A1     CH1 Analyte_1          0.66530      [0.63378, 0.69682]                 19959
3 WGR_1         1 Analyte_1_Analyte_2   A2     CH1 Analyte_1          0.70457      [0.67046, 0.73868]                 21137
4 WGR_1         1 Analyte_1_Analyte_2   A3     CH1 Analyte_1          0.70375      [0.67165, 0.73585]                 21112
6 WGR_2         1 Analyte_1_Analyte_2   B1     CH1 Analyte_1          2.22466      [2.13628, 2.31304]                 66740
7 WGR_2         1 Analyte_1_Analyte_2   B2     CH1 Analyte_1          2.14401       [2.0596, 2.22842]                 64320
8 WGR_2         1 Analyte_1_Analyte_2   B3     CH1 Analyte_1          2.23120      [2.14231, 2.32009]                 66936
  Analyte.Concentration..cp.ml. Recovery.Rate.... Total.Beads.per.Bead.Type Valid.Beads Negative.Beads Positive.Beads Negative.Valid.Beads
2                       3991800               NaN                     30000        3637           1874           1763              0.51526
3                       4227400               NaN                     30000        3354           1664           1690              0.49612
4                       4222400               NaN                     30000        3772           1875           1897              0.49708
6                      13348000               NaN                     30000        3918            437           3481              0.11154
7                      12864000               NaN                     30000        4062            476           3586              0.11718
8                      13387200               NaN                     30000        4041            434           3607              0.10740
  Fluorescence.Threshold..AU. Positive.Negative.Fluorescence..Lift. Mean.Bead.Width..µm. Mean.Core.Width..µm. Sample Notes
2                        11.7                                  2.62                 86.1                 43.3  HIV-1    NA
3                        11.7                                  2.88                 85.3                 42.5  HIV-1    NA
4                        11.7                                  2.59                 88.0                 42.3  HIV-1    NA
6                        10.6                                  4.09                 88.8                 42.9    CD3    NA
7                        10.6                                  3.94                 88.6                 42.0    CD3    NA
8                        10.6                                  4.19                 88.7                 42.9    CD3    NA 

Basically I want to individual threshold lines instead of the average line I have so it will look more like this:

blue graph shows individual lines

Any thoughts on the best approach to this?

1

There are 1 answers

1
Allan Cameron On BEST ANSWER

You cannot use geom_hline here. I would use geom_errorbar with the same ymin and ymax for each well. This gives a horizontal line across each well at the desired value:

ggplot(data = BlinkRes, aes(x = well, y = FluoCont, fill = Validity)) +
  geom_point(position = position_jitter(), shape = 21) +
  geom_errorbar(inherit.aes = FALSE, data = repthresh, linewidth = 1,
               aes(x = well, ymax = Fluoresence.Threshold..AU.,
                   ymin = Fluoresence.Threshold..AU.)) +
  scale_fill_manual(values = scalecols1,
                    breaks = scalebreaks1,
                    labels = scalelabs1) +
  ylab("Fluorescence Signal") +
  xlab("Well") +
  theme_light() +
  theme(axis.title.y = element_text(size = 16, family = "sans"), 
        legend.text = element_text(size = 16, family = "sans"),
        axis.text.x = element_text(colour ="black", size = 16, family = "sans"),
        axis.text.y = element_text(colour ="black", size = 16, family = "sans"),
        axis.title.x = element_text(colour = "black", size = 16, family = "sans"),
        legend.title = element_text(size = 16, family = "sans"),
        panel.background = element_blank(),
        axis.line = element_line(colour = "black"),
        plot.title = element_text(size = 10, hjust = 0.5)) +
  guides(fill=guide_legend(title="Bead Validity"))

enter image description here


Data used - reverse engineered from image in question

set.seed(1)

BlinkRes <-
data.frame(well = rep(c('A1', 'A2', 'A3', 'B1', 'B2', 'B3'), each = 5000),
FluoCont = c(rnorm(1000, 7), rnorm(4000, 15,),
            rnorm(1000, 7), rnorm(4000, 15),
            rnorm(1000, 7), rnorm(4000, 15),
            rnorm(1000, 5, 0.8), rnorm(4000, 20, 3),
            rnorm(1000, 5, 0.8), rnorm(4000, 20, 3),
            rnorm(1000, 5, 0.8), rnorm(4000, 20, 3)),
Validity = c(rep('Invalid', 1000), 
            sample(c('HIV-1 Valid', 'Invalid'), 4000, prob = c(0.9, 0.1), TRUE),
            rep('Invalid', 1000), 
            sample(c('HIV-1 Valid', 'Invalid'), 4000, prob = c(0.9, 0.1), TRUE),
            rep('Invalid', 1000),
            sample(c('HIV-1 Valid', 'Invalid'), 4000, prob = c(0.9, 0.1), TRUE),
            rep('Invalid', 1000), 
            sample(c('CD3 Valid', 'Invalid'), 4000, prob = c(0.9, 0.1), TRUE),
            rep('Invalid', 1000), 
            sample(c('CD3 Valid', 'Invalid'), 4000, prob = c(0.9, 0.1), TRUE),
            rep('Invalid', 1000), 
            sample(c('CD3 Valid', 'Invalid'), 4000, prob = c(0.9, 0.1), TRUE)))

scalecols1 <- c(`CD3 Valid` = '#db9aa8', `HIV-1 Valid` = '#92edf7', 
                Invalid = '#8a8a8a')
scalebreaks1 <- c('HIV-1 Valid', 'CD3 Valid')
scalelabs1 <-  c('HIV-1 Valid', 'CD3 Valid')

repthresh <- data.frame(well = c('A1', 'A2', 'A3', 'B1', 'B2', 'B3'),
                    Fluoresence.Threshold..AU. = rep(c(11.7, 10.6), each = 3))