0

plot

I want to add on this plot the weekday as text on top of the bars. The only function to add text in ggplot I found, is "annotate", which does not work the way I want.

It should look like this:

Plot with weekdays

geom_text gives me this Geom_text

My code:

    ggplot(data = filter(T2G2_dayav, site %in% c("S17S", "S17N"), !is.na(distance)),
       mapping = aes(as.factor(x = date_days))) +
  geom_col(mapping = aes(y = T2pn_av, fill = as.factor(distance)), 
           position = position_dodge(width = 0.9)) +

  theme_bw() + ylab("Particle Number (#/cm³), day-av") + xlab("Date") +
  scale_y_continuous(limits = c(0, 30000)) +
  scale_fill_discrete(name = "T2, Distance from road (m)") + 
  scale_color_grey(name = "Reference intrument G2") + 
  ggtitle("Day-averaged Particle Number (PN) per distance")

the head of my data:

distance  date_days  site  T2pn_av T2pn_avambient T2wdir_med weekday       Date  G2pn_av G2pn_min G2pn_max   G2ws_av G2ws_min G2ws_max G2wdir_med
     <int>     <dttm> <chr>    <dbl>          <dbl>      <dbl>   <chr>     <dttm>    <dbl>    <dbl>    <dbl>     <dbl>    <dbl>    <dbl>      <dbl>
1      -10 2017-07-18  S17N 28814.83      16917.831        110      Di 2017-07-18 13655.29     4621   105100 0.6781284        0      3.6       51.0
2      -10 2017-07-19  S17N 24210.95      15565.951        100      Mi 2017-07-19 10627.73     2908    67250 1.3673618        0      5.5       70.0
3      -10 2017-07-24  S17N 16143.44       7907.442         80      Mo 2017-07-24 11686.54     3582    55080 0.8178753        0      4.8       95.5
4      -10 2017-07-29  S17N 11762.56       5574.563        270      Sa 2017-07-29 12180.73     5413    45490 1.0304985        0      5.7      265.0
5      -10 2017-07-30  S17N 12138.22       6360.225        290      So 2017-07-30 10404.75     6113    23860 1.2385791        0      6.6      274.0
6      -10 2017-07-31  S17N 13815.32       9008.320        270      Mo 2017-07-31 11849.89     4595    46270 0.8554044        0      4.4      230.0

dput(head(T2G2_dayav))

structure(list(distance = c(-10L, -10L, -10L, -10L, -10L, -10L
), date_days = structure(c(1500328800, 1500415200, 1500847200, 
1501279200, 1501365600, 1501452000), class = c("POSIXct", "POSIXt"
), tzone = "Europe/Berlin"), site = c("S17N", "S17N", "S17N", 
"S17N", "S17N", "S17N"), T2pn_av = c(28814.8306772908, 24210.9512670565, 
16143.442364532, 11762.5630630631, 12138.2247114732, 13815.3198380567
), T2pn_avambient = c(16917.8306772908, 15565.9512670565, 7907.44236453202, 
5574.56306306306, 6360.22471147318, 9008.31983805668), T2wdir_med = c(110, 
100, 80, 270, 290, 270), weekday = c("Di", "Mi", "Mo", "Sa", 
"So", "Mo"), Date = structure(c(1500328800, 1500415200, 1500847200, 
1501279200, 1501365600, 1501452000), class = c("POSIXct", "POSIXt"
), tzone = "Europe/Berlin"), G2pn_av = c(13655.2885517401, 10627.7329973352, 
11686.5429216867, 12180.7308516181, 10404.7472642001, 11849.8893070109
), G2pn_min = c(4621, 2908, 3582, 5413, 6113, 4595), G2pn_max = c(105100, 
67250, 55080, 45490, 23860, 46270), G2ws_av = c(0.678128438241936, 
1.36736183524505, 0.817875347544022, 1.0304984658137, 1.23857912107, 
0.855404388351763), G2ws_min = c(0, 0, 0, 0, 0, 0), G2ws_max = c(3.6, 
5.5, 4.8, 5.7, 6.6, 4.4), G2wdir_med = c(51, 70, 95.5, 265, 274, 
230)), .Names = c("distance", "date_days", "site", "T2pn_av", 
"T2pn_avambient", "T2wdir_med", "weekday", "Date", "G2pn_av", 
"G2pn_min", "G2pn_max", "G2ws_av", "G2ws_min", "G2ws_max", "G2wdir_med"
), row.names = c(NA, -6L), class = c("grouped_df", "tbl_df", 
"tbl", "data.frame"), vars = c("distance", "date_days"), drop = TRUE, indices = list(
    0L, 1L, 2L, 3L, 4L, 5L), group_sizes = c(1L, 1L, 1L, 1L, 
1L, 1L), biggest_group_size = 1L, labels = structure(list(distance = c(-10L, 
-10L, -10L, -10L, -10L, -10L), date_days = structure(c(1500328800, 
1500415200, 1500847200, 1501279200, 1501365600, 1501452000), class = c("POSIXct", 
"POSIXt"), tzone = "Europe/Berlin")), row.names = c(NA, -6L), class = "data.frame", vars = c("distance", 
"date_days"), drop = TRUE, .Names = c("distance", "date_days"
)))
Tino
  • 2,091
  • 13
  • 15

1 Answers1

2

The idea is that you add a text on top of every bar (that's why vjust = 0, but you could also do vjust = -.5 to allow more space or vjust = 1.5 to put it in the bars, which is nice as well). The rest within the geom_text ist basically the same as in geom_col. But in general, you could put commonly used aesthetics in the first occurency within ggplot(aes(...)), as you already did with the x-value.

ggplot(data = filter(T2G2_dayav, site %in% c("S17S", "S17N"), !is.na(distance)),
       mapping = aes(as.factor(x = date_days))) +
  geom_col(mapping = aes(y = T2pn_av, fill = as.factor(distance)), 
           position = position_dodge(width = 0.9)) +
  geom_text(aes(label = weekday, y = T2pn_av), vjust = -.5, # add these
            position = position_dodge(width = 0.9)) + # lines
  theme_bw() + ylab("Particle Number (#/cm³), day-av") + xlab("Date") +
  scale_y_continuous(limits = c(0, 30000)) +
  scale_fill_discrete(name = "T2, Distance from road (m)") + 
  scale_color_grey(name = "Reference intrument G2") + 
  ggtitle("Day-averaged Particle Number (PN) per distance")

enter image description here

The following should solve your problem with too many labels. It takes the highest label and places it in the center of the bars of that x-value. Find a plot below with additional rows added to your data:

T2G2_dayav <- rbind(T2G2_dayav %>% ungroup(), T2G2_dayav %>% ungroup() %>% mutate(distance = 5)) # add more observations for testing

T2G2_dayav <- T2G2_dayav %>% mutate(T2pn_av = ifelse(distance == 5, T2pn_av/2, T2pn_av)) # label only the highest bar

The following should work with your data:

ggplot(data = filter(T2G2_dayav, site %in% c("S17S", "S17N"), !is.na(distance)) %>% 
    group_by(date_days) %>% # group by days
    mutate(weekday2 = ifelse(T2pn_av == max(T2pn_av), weekday, NA)), # within each day (group), only label the highest
       mapping = aes(as.factor(x = date_days))) +
    geom_col(mapping = aes(y = T2pn_av, fill = as.factor(distance)), 
             position = position_dodge(width = 0.9)) +
    geom_text(aes(label = weekday2, y = T2pn_av), vjust = -.5, # add these
              position = position_dodge(with = 0.9)) + # lines
    theme_bw() + ylab("Particle Number (#/cm³), day-av") + xlab("Date") +
    scale_y_continuous(limits = c(0, 30000)) +
    scale_fill_discrete(name = "T2, Distance from road (m)") + 
    scale_color_grey(name = "Reference intrument G2") + 
    ggtitle("Day-averaged Particle Number (PN) per distance")

enter image description here

Tino
  • 2,091
  • 13
  • 15
  • This is quite helpful. But since there are 9 Bar per days, it creates 9 seperate textfields per day. – paviannaidoo Oct 26 '17 at 12:13
  • In my data extract, there are only observations with a distance of -10. But in the entire data frame there are 9 different distances. For every distance there will be a bar. And it creates a text field for every bar – paviannaidoo Oct 26 '17 at 12:21
  • I see... should have had a closer look to your first plot above. But for the future, you should make sure that the sample data you provide is small, simple and still contains all the characteristics you need. Edited my solution accordingly. – Tino Oct 26 '17 at 12:46