1

I am plotting router statistics (collected from merlin speed monitoring tool).

The graphs are faceted by year-month, and I want each month's x axis to expand to the entire month, even when I only have part of a months data.

In the example below, the data for January 2022 is incomplete (just 6 hours or so of data).

The code I have tried:

library(tidyverse)
library(scales)
X.df <- read.csv(url("https://pastebin.com/raw/sGAzEDe6")) %>%
   mutate(date = as.POSIXct(date, origin="1970-01-01")) 

ggplot(X.df , aes(date, Download, colour = Download)) +
  geom_line()+
facet_wrap(~ month,  scale="free_x",  ncol = 1) +
    scale_colour_gradient(low="red",high="green", limits=c(0.0, 50), oob = squish) +
  scale_x_datetime(date_labels = "%d/%m", breaks = "7 day", minor_breaks = "1 day") +
  coord_cartesian(ylim = c(0, 60))

graph of router speeds

Again, I want the range of the x axis in each facet to cover the entire month. Thus, I want the X axis for the 2021-12 facet to run from 1st Dec 2021 to 31st Dec 2021, and the X axis for the 2022-01 facet to run from 1st Jan 2022 to 31st Jan 2022.

Is there some way of forcing this within ggplot2?

An additional, smaller self-contained example to try your code on:

X.df <- tribble(
  ~date, ~month, ~Download,
"2021-12-01T00:30:36Z","2021-12",20.13,
"2021-12-07T06:30:31Z","2021-12",38.95,
"2021-12-14T08:00:31Z","2021-12",38.44,
"2021-12-21T09:30:29Z","2021-12",28.57,
"2021-12-28T16:00:31Z","2021-12",30.78,
"2021-12-31T13:00:28Z","2021-12",55.45,
"2022-01-01T00:00:28Z","2022-1",55.44,
"2022-01-01T02:30:29Z","2022-1",55.63,
"2022-01-01T03:00:29Z","2022-1",55.75,
"2022-01-01T05:00:29Z","2022-1",55.8,
"2022-01-07T03:00:29Z","2022-1",53.6,
"2022-01-07T05:00:29Z","2022-1",51.8
)

As always, thanks in advance. Pete

Henrik
  • 65,555
  • 14
  • 143
  • 159
PJP
  • 612
  • 1
  • 6
  • 18
  • If I understand the question, just remove `scale="free_x"`? – Rui Barradas Jan 01 '22 at 13:08
  • Also, use `date_breaks`, not `breaks`. – Rui Barradas Jan 01 '22 at 13:14
  • Rui - that doesn't work - it scales the X axis for the whole of the data set, so the X axis runs from 1st Dec to 1st Jan, not 1st Jan to the 31st Jan for the lower graph. – PJP Jan 01 '22 at 13:40
  • 1
    Hi @PJP! Please make your question self-contained, i.e. create an easily copy-paste-able _minimal_ data in the actual question, instead of relying on a link that may become obsolete at any time. This will increase the value of your post to future visitors. Three-four dates per "year-month" should be enough to illustrate your issue. Also. the desired output of plots may be tricky to describe in words and often results in futile guesses, like below. Thus, feel free to add a simple drawing that shows the desired result. Cheers – Henrik Jan 01 '22 at 14:15
  • Does this answer your question? [ggplot2 change axis limits for each individual facet panel](https://stackoverflow.com/questions/51735481/ggplot2-change-axis-limits-for-each-individual-facet-panel) – Dan Adams Jan 01 '22 at 15:26
  • @Henrik - is it OK that I added the self contained example as above as an edit ? – PJP Jan 02 '22 at 14:43
  • 1
    @PJP Nice, thanks a lot! I made some small edits - I hope you find them OK. Cheers – Henrik Jan 02 '22 at 15:27
  • 1
    Regarding my removal of "EDIT", please refer to this post: [Should "Edit:" in edits be discouraged?](https://meta.stackoverflow.com/questions/255644/should-edit-in-edits-be-discouraged); removal of "answer" in question: [When is it cool to summarize answers in question edit?](https://meta.stackoverflow.com/questions/336441/when-is-it-cool-to-summarize-answers-in-question-edit) – Henrik Jan 02 '22 at 15:39
  • @DanAdams - Hi Dan - I had seen that post on SO, but it didn't do what I required (partly because it would required pre-programming the x axis for each month of the year). The accepted answer does the job brilliantly. – PJP Jan 03 '22 at 10:23

1 Answers1

2

Updat II: Removed prior versions:

  1. In your database there is only one january 2022 date
  2. in the dataframe we complete the dates of januare of 2022 using complete from tidyr package.
library(tidyverse)
library(lubridate)
X.df %>% 
  mutate(date = ymd(date)) %>% 
  group_by(month(date)) %>% 
  complete(date = seq(min(date), max(ceiling_date(date, unit = "month") - ddays(1)), by = 'day')) %>%
  fill(month) %>% 
  ggplot(aes(x = date, Download, colour = Download)) +
  geom_line()+
  facet_wrap(~ month,  scale="free_x",  ncol = 1) +
  scale_colour_gradient(low="red",high="green", limits=c(0.0, 50), oob = squish) +
  scale_x_date(date_breaks = "1 day", date_labels =  "%d/%m", expand = c(0, 0)) +
  coord_cartesian(ylim = c(0, 60))

enter image description here

TarJae
  • 72,363
  • 6
  • 19
  • 66
  • 1
    Please see my update! – TarJae Jan 01 '22 at 16:26
  • 2
    @PJP This should be the accepted answer. But I would substitute `geom_point() + geom_smooth(method = 'gam', formula = y ~ s(x, bs = "cs"))` for `geom_line`. – Rui Barradas Jan 01 '22 at 17:36
  • 1
    @TarJae - Excellent - that does the job. Thank you. Can you explain why the group_by is necessary (I played around with your code and it doesn't work without the group_by). – PJP Jan 02 '22 at 11:20
  • 1
    `group_by` refers to `complete`. Without `group_by` the whole year 2022 will be completed. Maybe you should add `ungroup()` after `complete`. :-) – TarJae Jan 02 '22 at 14:51