0

I'm wondering whether someone can help me in applying the facetscales package to create different date ranges for each facet. I know something similar can be achieved using scales = "free_x" in the call to ggplot, but I am hoping to use this to also programmatically determine the number of days by which each facet's scale should be expanded.

I have seen a related question answered here (see Uwe's answer), but I cannot get the code to evaluate correctly with dates.

I have included a short example of my data below. From Uwe's answer to the question, the I expect a list of ggplot ggproto objects that can be included as a list in the plotting function, however, the code does not seem to evaluate the dates properly.

Any help much appreciated.

df <- structure(list(zone = c("zone1", "zone1", "zone1", "zone1", "zone1", 
                                                            "zone1", "zone1", "zone1", "zone1", "zone1", "zone2", "zone2", 
                                                            "zone2", "zone2", "zone2", "zone2", "zone2", "zone2", "zone2", 
                                                            "zone2"), date = structure(c(16294, 16295, 16296, 16297, 16298, 
                                                                                                                     16299, 16300, 16301, 16302, 16303, 16304, 16305, 16306, 16307, 
                                                                                                                     16308, 16309, 16310, 16311, 16312, 16313), class = "Date"), Q = c(317, 
                                                                                                                                                                                                                                                        299, 290, 276, 277, 238, 239, 266, 278, 278, 93, 102, 107, 124, 
                                                                                                                                                                                                                                                        122, 110, 93, 89, 85, 92)), class = c("grouped_df", "tbl_df", 
                                                                                                                                                                                                                                                                                                                                    "tbl", "data.frame"), row.names = c(NA, -20L), groups = structure(list(
                                                                                                                                                                                                                                                                                                                                        zone = c("zone1", "zone2"), .rows = list(1:10, 11:20)), row.names = c(NA, 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    -2L), class = c("tbl_df", "tbl", "data.frame"), .drop = TRUE))


facet_params <- df %>% 
    group_by(zone) %>%
    summarise(start_date=min(date, na.rm=TRUE), end_date=max(date, na.rm=TRUE)) %>%
    mutate(duration = end_date-start_date, 
                 extra_days = trunc(as.integer(duration)*.3),
                 breaks=c(2,4))

scales_y <- facet_params %>% 
    str_glue_data(
        "`{zone}` = scale_x_date(limits = c({as.Date(start_date)}, {as.Date(end_date)}), ", 
        "breaks = seq({as.Date(start_date)}, {as.Date(end_date)}, {breaks}))") %>%
    str_flatten(", ") %>% 
    str_c("list(", ., ")") %>% 
    parse(text = .) %>% 
    eval()
nickb
  • 319
  • 2
  • 12
  • Any particular reason you're attached to the 'computing on the language' part of his answer? It seems to me that his first codeblock is more straightforward to implement. – teunbrand Sep 01 '19 at 10:04
  • Hi teunbrand, the reason is that i need to implement this programmatically as part of a plotting process with ‘purrr::pmap’. – nickb Sep 01 '19 at 10:58

1 Answers1

1

I'm no expert in computing on the language, but as you mentioned, the dates weren't being evalued as proper dates. The error messages seemed to suggest that the dates were being interpreted as the mathematical expression 2014 - 8 - 12 (= 1994). To fix this, I've moved the as.Date() function outside the brackets and put single quotation marks around the brackets. Now, the dates are evaluated as "2014-8-12" which as.Date() can see as proper dates. Also I've replaced seq() with seq.Date(), but I don't know if that is absolutely necessary. The code below worked for me:

scales_x <- facet_params %>% 
  str_glue_data(
    "`{zone}` = scale_x_date(limits = c(as.Date('{start_date}'), as.Date('{end_date}')), ", 
    "breaks = seq.Date(as.Date('{start_date}'), as.Date('{end_date}'), {breaks}))"
  ) %>%
  str_flatten(", ") %>% 
  str_c("list(", ., ")") %>% 
  parse(text = .) %>% 
  eval()

library(facetscales)

ggplot(df, aes(date, Q)) +
  geom_line() +
  facet_grid_sc(~ zone, scales = list(x = scales_x))
teunbrand
  • 33,645
  • 4
  • 37
  • 63