Search code examples
rggplot2fill

How to set fill opacity separately to outline opacity in ggplot geompoint?


I'm creating a scatter plot with ggplot2 and I want to have my points with a solid outer line and a partly opaque fill. Using geom_point with shape 21, I can set the outline to a different colour to the fill, but I can't figure out how to set the opacity of the fill independently to the outline. Here's my code:

  p <- ggplot(
    data=raw_data, 
    aes(
      x=acq_time, 
      y=rt,
      size=area,
      color=compound,
      text=paste(compound,
                 paste(arl_no, " - ", sample_name),
                 paste("Acq. method =", acq_meth),
                 paste("Processing method =", proc_meth),
                 paste("RT =", rt, "  Peak area =", area, "  Area percent =", area_percent),
                 path,
                 sep="\n"))) +
    geom_point(shape=21, aes(fill=compound, alpha=0.3)) +
    labs(title = "Compound retention times")

  p_interactive<-ggplotly(p, tooltip="text")
  p_interactive

And here's some sample data:

    > dput(sample_data)
structure(list(peak = c(29L, 13L, 13L, 27L, 52L, 6L, 110L, 121L, 
2L, 16L, 15L, 4L, 11L, 12L, 3L, 27L, 12L, 14L, 7L, 4L, 20L, 14L, 
5L, 16L, 22L, 21L), rt = c(12.555, 10.794, 10.719, 12.818, 17.313, 
9.287, 19.816, 19.697, 7.769, 10.913, 10.569, 9.067, 10.159, 
10.909, 7.982, 12.979, 10.359, 10.573, 9.919, 7.771, 11.783, 
10.572, 9.4, 10.573, 9.952, 11.8), type = c("VV", "VB", "BV", 
"VV", "VB", "VB", "VV", "VV", "BB", "VB", "VV", "BV", "VV", "VB", 
"BB", "VB", "VV", "VV", "BV", "VB", "VV", "VV", "VV", "VB", "VV", 
"VB"), width = c(0.0215, 0.0228, 0.0208, 0.0237, 0.0239, 0.0227, 
0.0255, 0.032, 0.0265, 0.0224, 0.0241, 0.0237, 0.0225, 0.023, 
0.0284, 0.023, 0.021, 0.0244, 0.0212, 0.0268, 0.0217, 0.0248, 
0.0242, 0.0247, 0.0228, 0.0231), area = c(70.51088, 207.4633, 
154.9167, 26.83362, 199.3089, 65.4397, 11.2647, 50.90956, 71.16205, 
992.8403, 160.18407, 31.15576, 73.49612, 1487.48621, 123.06009, 
40.85532, 119.6302, 190.15558, 38.30812, 2.57459, 5.102, 281.16638, 
55.96363, 297.8779, 492.08939, 6.97452), area_percent = c(0.4212, 
2.6688, 1.9341, 0.2938, 2.6138, 0.7597, 0.1401, 0.3254, 0.7343, 
11.0654, 2.0277, 0.33, 0.9087, 20.10661, 1.5192, 0.2705, 0.7815, 
2.1007, 0.4619, 0.0305, 0.0648, 2.9014, 0.6735, 1.8652, 5.8267, 
0.0696), compound = c("cis-p-menth-2-en-1-ol", "1,8-cineole", 
"p-cymene", "trans-p-menth-2-en-1-ol", "aromadendrene", "myrcene", 
"viridiflorol", "globulol", "a-thujene", "g-terpinene", "1,8-cineole", 
"sabinene", "limonene", "g-terpinene", "a-pinene", "trans-p-menth-2-en-1-ol", 
"limonene", "1,8-cineole", "a-phellandrene", "a-thujene", "linalool", 
"1,8-cineole", "b-pinene", "1,8-cineole", "a-terpinene", "linalool"
), total_peak_area = c(16739, 7773.547, 8009.608, 9133.66006, 
7625.237, 8613.372, 8039.38068, 15647.1, 9690.86738, 8972.451, 
7899.82093, 9440.86063, 8088.34658, 7085.32236, 8100.07186, 15103.2, 
15307.2, 9051.95117, 8293.793, 8445.46604, 7873.55789, 9690.86738, 
8308.918, 15970.3, 8445.46604, 10024.4), arl_no = c("QSR0047-2_1", 
"ARL2306177", "ARL2306124", "REFTTO-230301_1", "ARL2305596", 
"QSR0047-230508_2", "REFTTO-230203_2", "ARL2104967_QSR_CANDIDATE_1", 
"ARL2300833", "QSR0047-230525_2", "REFTTO-230118_2", "REFTTO-230314_1", 
"ARL2300523", "ARL2300053", "REFTTO-230202_2", "QSR0047-2_2", 
"QSR0047-2_2", "REFTTO-230308_1", "QSR0047-2_1", "ARL2300518", 
"REFTTO-230116_2", "ARL2300833", "QSR0047-2_2", "ARL2104967_QSR_CANDIDATE_2", 
"ARL2300518", "QSR0047_1"), sample_name = c("a", "b", "c", "d", 
"e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", 
"r", "s", "t", "u", "v", "w", "x", "y", "z"), acq_time = structure(c(19593, 
19585, 19585, 19417, 19564, 19485, 19391, 19464, 19397, 19502, 
19375, 19430, 19387, 19362, 19390, 19583, 19584, 19424, 19565, 
19387, 19373, 19397, 19565, 19440, 19387, 19541), class = "Date"), 
    acq_meth = c("EO BASEMETHOD 2020", "EO BASEMETHOD 2020", 
    "EO BASEMETHOD 2020", "EO BASEMETHOD 2020", "EO BASEMETHOD 2020", 
    "EO BASEMETHOD 2020", "EO BASEMETHOD 2020", "EO BASEMETHOD 2020", 
    "EO BASEMETHOD 2020", "EO BASEMETHOD 2020", "EO BASEMETHOD 2020", 
    "EO BASEMETHOD 2020", "EO BASEMETHOD 2020", "EO BASEMETHOD 2020", 
    "EO BASEMETHOD 2020", "EO BASEMETHOD 2020", "EO BASEMETHOD 2020", 
    "EO BASEMETHOD 2020", "EO BASEMETHOD 2020", "EO BASEMETHOD 2020", 
    "EO BASEMETHOD 2020", "EO BASEMETHOD 2020", "EO BASEMETHOD 2020", 
    "EO BASEMETHOD 2020", "EO BASEMETHOD 2020", "EO BASEMETHOD 2020"
    ), proc_meth = c("TTO.M", "TTO.M", "TTO.M", "TTO.M", "TTO.M", 
    "TTO.M", "TTO.M", "TTO.M", "TTO.M", "TTO.M", "TTO.M", "TTO.M", 
    "TTO.M", "TTO.M", "TTO.M", "TTO.M", "TTO.M", "TTO.M", "TTO.M", 
    "TTO.M", "TTO.M", "TTO.M", "TTO.M", "TTO.M", "TTO.M", "TTO LATE FRACTION SCB.M"
    ), gc = c("GC-3", "GC-3", "GC-3", "GC-3", "GC-3", "GC-3", 
    "GC-3", "GC-3", "GC-3", "GC-3", "GC-3", "GC-3", "GC-3", "GC-3", 
    "GC-3", "GC-3", "GC-3", "GC-3", "GC-3", "GC-3", "GC-3", "GC-3", 
    "GC-3", "GC-3", "GC-3", "GC-3"), path = c("A", "B", "C", 
    "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", 
    "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z")), row.names = c(28411L, 
28045L, 27962L, 7910L, 25994L, 11854L, 5880L, 10612L, 6691L, 
14799L, 1626L, 8904L, 4163L, 171L, 5135L, 27743L, 27885L, 8465L, 
26208L, 4031L, 1470L, 6701L, 26231L, 9626L, 4037L, 19499L), class = "data.frame")

Note that plot_ly creates the type of effect that I'm looking for by default, but I'm using ggplot with ggplotly because ggplot seems to give me more flexibility with what I can include in the hover text. But here's a plot_ly approach that at least shows the type of look that I'm going for:

fig <- plot_ly(type="scatter", mode="markers", sizes=c(20,1000),alpha=0.3)
  fig <- fig %>%
    add_trace(data=raw_data,
              x=~acq_time, 
              y = ~rt, 
              size=~area,
              color=~compound, 
              text=~compound,
              hovertemplate=paste("<b>%{text}</b>",
                                  '<br>RT = %{y}',
                                  '<br>Date = %{x}')) %>%
    layout(title="Compound retention times")
    fig

Solution

  • Map the color aesthetic to compound, and set the fill aesthetic to after_scale(alpha(color, 0.2)))

    ggplot(raw_data, aes(acq_time, rt, size = area, color = compound)) +
      geom_point(aes(fill = after_scale(alpha(color, 0.2))), shape = 21) +
      labs(title = "Compound retention times") +
      theme_minimal()
    

    enter image description here