How to put axes behind the graph?
Asked Answered
L

2

11

I created a graph using geom_line and geom_point via ggplot. I want my axes to meet at (0,0) and I want my lines and data points to be in front of the axes instead of behind as shown:

graph

I've tried:

  1. coord_cartesian(clip = 'off')
  2. putting geom_line and geom_point at the end
  3. creating a base graph then add geom_line and geom_point
  4. playing around with the functions of coord_cartesian
  5. manually setting xlim =c(-0.1, 25) and ylim=c(-0.1, 1500)

data7 is as follows:

   Treatment Days N        mean         sd          se
1          1    0 7 204.7000000  41.579963  15.7157488
2          1    2 7 255.0571429  41.116617  15.5406205
3          1    5 7 290.6000000  49.506498  18.7116974
4          1    8 7 330.8142857  49.044144  18.5369442
5          1   12 7 407.5142857  95.584194  36.1274294
6          1   15 7 540.8571429 164.299390  62.0993323
7          1   19 7 737.5285714 308.786359 116.7102736
8          1   21 7 978.4571429 502.506726 189.9296898
9          2    0 7 205.7428571  46.902482  17.7274721
10         2    2 7 227.5571429  47.099889  17.8020846
11         2    5 7 232.4857143  59.642922  22.5429054
12         2    8 7 247.9857143  66.478529  25.1265220
13         2   12 7 272.0428571  79.173162  29.9246423
14         2   15 7 289.1142857  82.847016  31.3132288
15         2   19 7 312.3857143 105.648591  39.9314140
16         2   21 7 334.7142857 121.569341  45.9488920
17         3    0 7 212.2285714  47.549263  17.9719320
18         3    2 7 235.4142857  52.689671  19.9148237
19         3    5 7 177.0714286  54.895225  20.7484447
20         3    8 7 205.2571429  72.611451  27.4445489
21         3   12 7 247.8142857 119.369558  45.1174522
22         3   15 7 280.4285714 140.825847  53.2271669
23         3   19 7 366.9142857 210.573799  79.5894149
24         3   21 7 451.0428571 289.240793 109.3227438
25         4    0 7 211.6857143  24.329161   9.1955587
26         4    2 7 227.8428571  28.762525  10.8712127
27         4    5 7 205.9428571  49.148919  18.5765451
28         4    8 7 153.1142857  25.189246   9.5206399
29         4   12 7 128.2571429  43.145910  16.3076210
30         4   15 7 104.1714286  45.161662  17.0695038
31         4   19 7  85.4714286  51.169708  19.3403318
32         4   21 7  66.9000000  52.724567  19.9280133
33         5    0 7 216.7857143  39.957829  15.1026398
34         5    2 7 212.2000000  27.037135  10.2190765
35         5    5 7 115.5000000  37.094070  14.0202405
36         5    8 7  46.1000000  34.925492  13.2005952
37         5   12 7  29.3142857  24.761222   9.3588621
38         5   15 6  10.0666667  13.441974   5.4876629
39         5   19 6   6.4000000  11.692733   4.7735382
40         5   21 6   5.3666667  12.662017   5.1692467
41         6    0 7 206.6857143  40.359155  15.2543269
42         6    2 7 197.0428571  40.608327  15.3485048
43         6    5 7 106.2142857  58.279654  22.0276388
44         6    8 7  46.0571429  62.373014  23.5747833
45         6   12 7  31.7571429  49.977457  18.8897031
46         6   15 7  28.1142857  45.437995  17.1739480
47         6   19 7  26.2857143  38.414946  14.5194849
48         6   21 7  32.7428571  53.203003  20.1088450
49         7    0 7 193.2000000  37.300447  14.0982437
50         7    2 7 133.2428571  26.462606  10.0019250
51         7    5 7   3.8142857   7.445900   2.8142857
52         7    8 7   0.7142857   1.496026   0.5654449
53         7   12 7   0.0000000   0.000000   0.0000000
54         7   15 7   0.0000000   0.000000   0.0000000
55         7   19 7   0.0000000   0.000000   0.0000000
56         7   21 7   0.0000000   0.000000   0.0000000

My code is as follows:

ggplot(data7, aes(Days, mean, color=Treatment)) +
  geom_line() +
  geom_errorbar(aes(ymin=mean-se, ymax=mean+se), width=0.5, size= 0.25) +
  geom_point(size=2.5) +
  scale_colour_hue(limits = c("1", "2", "3", "4", "5", "6", "7")) +
  scale_x_continuous(expand = c(0, 0), limits = c(0, NA), breaks = scales::pretty_breaks(n = 10)) +
  scale_y_continuous(expand = c(0, 0), limits = c(0, NA), breaks = scales::pretty_breaks(n = 8)) +
  theme_classic() +
  theme(axis.text = element_text(color = "#000000"), plot.title = element_text(hjust = 0.5)) +
  coord_cartesian(clip = 'off')
Levine answered 6/6, 2020 at 20:2 Comment(5)
Can you either post enough sample data to reproduce this, or shift to a base-R dataset?Lantz
@Lantz I have edited the post with the data! Thanks for helping me out!Levine
It might be just me, but ... my y-axis is not at x=0, it's a little left of it.Lantz
@Lantz Hmm, what about your x-axis? I ideally would like the axes to cross exactly at 0,0 and having data start from the axes instead of having them float around if that makes sense, haha.Levine
Fortunately (for me), my answer below forces the 0,0 intersection :-), hope it works (or at least helps).Lantz
L
6

Here's one approach that omits the axis lines/ticks and then explicitly layers them below the rest of the plot layers. Because the new lines/ticks are drawn as literal objects, they will then ignore any other theming you may later apply. With control comes responsibility ...

This method has the side-effect of a "simple" axis tick, just the + symbol, which shows as a cross-line at each point. This is in contrast to the standard way (typically just pointing outwards). I'm guessing that something more robust could be devised, but I thought "simple" up-front could be adapted in other ways.

Taking the literal code of your ggplot(...) + ... and storing as gg, no changes. First we'll extract the tick marks. If you are confident enough (or not OCD-enough) to determine the tick locations yourself, then feel free to hard-code it. This method (of using ggplot_build then extracting the ...$x$breaks) has the advantage of matching the tick and label locations, especially if they might change with different/updated data.

ticks <- with(ggplot_build(gg)$layout$panel_params[[1]],
              na.omit(rbind(
                data.frame(x = x$breaks, y = 0),
                data.frame(x = 0, y = y$breaks)
              )))
head(ticks,3); tail(ticks,3)
#   x y
# 1 0 0
# 2 2 0
# 3 4 0
#    x    y
# 16 0  600
# 17 0  800
# 18 0 1000

From here, I'll take a cue from https://mcmap.net/q/383875/-insert-layer-underneath-existing-layers-in-ggplot2-object and prepend some layers below all of the others. (This is where I identify the + symbol for axis ticks, using shape=3.)

gg$layers <- c(
  geom_hline(aes(yintercept = 0)),
  geom_vline(aes(xintercept = 0)),
  geom_point(data = ticks, aes(x, y), shape = 3, inherit.aes = FALSE),
  gg$layers)

Now we just plot the previously-generated gg, adding a cue to omit the theme axis lines/ticks.

gg + theme(axis.line = element_blank(), axis.ticks = element_blank())

enter image description here


Data, including converting Treatment to character (to avoid continuous/discrete warnings from scale_colour_hue):

data7 <- read.table(header=TRUE, text = "
   Treatment Days N        mean         sd          se
1          1    0 7 204.7000000  41.579963  15.7157488
2          1    2 7 255.0571429  41.116617  15.5406205
3          1    5 7 290.6000000  49.506498  18.7116974
4          1    8 7 330.8142857  49.044144  18.5369442
5          1   12 7 407.5142857  95.584194  36.1274294
6          1   15 7 540.8571429 164.299390  62.0993323
7          1   19 7 737.5285714 308.786359 116.7102736
8          1   21 7 978.4571429 502.506726 189.9296898
9          2    0 7 205.7428571  46.902482  17.7274721
10         2    2 7 227.5571429  47.099889  17.8020846
11         2    5 7 232.4857143  59.642922  22.5429054
12         2    8 7 247.9857143  66.478529  25.1265220
13         2   12 7 272.0428571  79.173162  29.9246423
14         2   15 7 289.1142857  82.847016  31.3132288
15         2   19 7 312.3857143 105.648591  39.9314140
16         2   21 7 334.7142857 121.569341  45.9488920
17         3    0 7 212.2285714  47.549263  17.9719320
18         3    2 7 235.4142857  52.689671  19.9148237
19         3    5 7 177.0714286  54.895225  20.7484447
20         3    8 7 205.2571429  72.611451  27.4445489
21         3   12 7 247.8142857 119.369558  45.1174522
22         3   15 7 280.4285714 140.825847  53.2271669
23         3   19 7 366.9142857 210.573799  79.5894149
24         3   21 7 451.0428571 289.240793 109.3227438
25         4    0 7 211.6857143  24.329161   9.1955587
26         4    2 7 227.8428571  28.762525  10.8712127
27         4    5 7 205.9428571  49.148919  18.5765451
28         4    8 7 153.1142857  25.189246   9.5206399
29         4   12 7 128.2571429  43.145910  16.3076210
30         4   15 7 104.1714286  45.161662  17.0695038
31         4   19 7  85.4714286  51.169708  19.3403318
32         4   21 7  66.9000000  52.724567  19.9280133
33         5    0 7 216.7857143  39.957829  15.1026398
34         5    2 7 212.2000000  27.037135  10.2190765
35         5    5 7 115.5000000  37.094070  14.0202405
36         5    8 7  46.1000000  34.925492  13.2005952
37         5   12 7  29.3142857  24.761222   9.3588621
38         5   15 6  10.0666667  13.441974   5.4876629
39         5   19 6   6.4000000  11.692733   4.7735382
40         5   21 6   5.3666667  12.662017   5.1692467
41         6    0 7 206.6857143  40.359155  15.2543269
42         6    2 7 197.0428571  40.608327  15.3485048
43         6    5 7 106.2142857  58.279654  22.0276388
44         6    8 7  46.0571429  62.373014  23.5747833
45         6   12 7  31.7571429  49.977457  18.8897031
46         6   15 7  28.1142857  45.437995  17.1739480
47         6   19 7  26.2857143  38.414946  14.5194849
48         6   21 7  32.7428571  53.203003  20.1088450
49         7    0 7 193.2000000  37.300447  14.0982437
50         7    2 7 133.2428571  26.462606  10.0019250
51         7    5 7   3.8142857   7.445900   2.8142857
52         7    8 7   0.7142857   1.496026   0.5654449
53         7   12 7   0.0000000   0.000000   0.0000000
54         7   15 7   0.0000000   0.000000   0.0000000
55         7   19 7   0.0000000   0.000000   0.0000000
56         7   21 7   0.0000000   0.000000   0.0000000")
data7$Treatment <- as.character(data7$Treatment)
Lantz answered 6/6, 2020 at 21:58 Comment(0)
N
4

A fairly straightforward way to do this is just to move the panel in front of the axes once the plot elements are created (i.e. as a grobTree). The grobTree contains a layout data frame which allows you to move plot elements forwards or backwards by adjusting their z component.

If you store your plot as p, then the code would be:

ggp <- ggplot_gtable(ggplot_build(p))
ggp$layout$z[which(ggp$layout$name == "panel")] <- max(ggp$layout$z) + 1
grid::grid.draw(ggp)

enter image description here


Plot code:

This is just the original plot except I have added a vline at 0 and an hline at 0 in case bringing the panel forwards clips your axis lines).

p <- ggplot(data7, aes(Days, mean, color=Treatment)) +
  geom_hline(aes(yintercept = 0)) +
  geom_vline(aes(xintercept = 0)) +
  geom_line() +
  geom_errorbar(aes(ymin=mean-se, ymax=mean+se), width=0.5, size= 0.25) +
  geom_point(size=2.5) +
  scale_colour_hue(limits = c("1", "2", "3", "4", "5", "6", "7")) +
  scale_x_continuous(expand = c(0, 0), limits = c(0, NA), breaks = scales::pretty_breaks(n = 10)) +
  scale_y_continuous(expand = c(0, 0), limits = c(0, NA), breaks = scales::pretty_breaks(n = 8)) +
  theme_classic() +
  theme(axis.text = element_text(color = "#000000"), plot.title = element_text(hjust = 0.5)) +
  coord_cartesian(clip = 'off')
Nyeman answered 6/6, 2020 at 23:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.