-2

Apologies, I'm very new to all of this.

I have this problem with my X-axis, where it is too overcrowded with dates and times. This can be seen in the graph that I have produced:

Graph produced so far

The data being used is the following:

Example Excel spreadsheet.

Ideally, I would like the X-axis to have the ticks for each hour, but the text to be split between nights, for example Night 1 (5 Feb - 6 Feb).

I have so far been able to sort out most issues but this one has stumped me for quite some time. How could I split the x-axis in to blocks of this nature?

Any help would be greatly, greatly appreciated.

Many thanks,
Leo

3
  • Please provide enough code so others can better understand or reproduce the problem. Commented Jul 9 at 11:20
  • 2
    Welcome to SO, Leo Lasrado! Please do not post (only) an image of code/data/errors: it breaks screen-readers and it cannot be copied or searched (ref: meta.stackoverflow.com/a/285557 and xkcd.com/2116). Please include the code, console output, or data (e.g., data.frame(...) or the output from dput(head(x))) directly into a code block. Commented Jul 9 at 13:01
  • I think first and foremost you need to work with native types like dates and such, see stackoverflow.com/q/56557922/3358272, stackoverflow.com/q/65647998/3358272, stackoverflow.com/q/66606315/3358272. This question starts as a duplicate of one of those due to using strings for the x-axis instead of Date- or POSIXt-class values. Once you resolve that, I think you can control the axis with scale_x_date (or *_datetime) using its date_labels= fairly well. Lacking usable data, I think the answer you have so far may be a good enough start. Commented Jul 9 at 15:23

1 Answer 1

2

Your first problem is that the hour_bin variable of your dataframe is probably a character vector, not a datetime. That means ggplot will try to render all the values of hours_bin on the x axis. To get a proper datetime axis, yo you need to convert text strings like "05/02/2025 21:00"to a datetime object. The {lubridate} package has functions to help you do that. Then you want some way of indicating when it's night. If you want a bracket on your axis, the {legendry} package has a function to help you do that.

For example:

library(ggplot2)
library(legendry)
library(dplyr)
library(lubridate)

df <- data.frame(
  hour_bin = c(
    "05/02/2025 18:00",
    "05/02/2025 19:00",
    "05/02/2025 20:00",
    "05/02/2025 21:00",
    "05/02/2025 22:00",
    "05/02/2025 23:00",
    "06/02/2025 00:00",
    "06/02/2025 01:00",
    "06/02/2025 02:00",
    "06/02/2025 03:00",
    "06/02/2025 04:00",
    "06/02/2025 05:00",
    "06/02/2025 18:00",
    "06/02/2025 19:00",
    "06/02/2025 20:00",
    "06/02/2025 21:00",
    "06/02/2025 22:00",
    "06/02/2025 23:00"
  ),
  mean_calling_activity = c(
    0.916666667,
    1,
    1,
    0.65,
    0.183333333,
    0.133333333,
    0.066666667,
    0.083333333,
    0,
    0,
    0,
    0.183333333,
    0.65,
    1,
    1,
    0.966666667,
    0.533333333,
    0.083333333
  )
)

# convert datestrings to datetime
df <- df |>
  dplyr::mutate(
    hour_bin = lubridate::parse_date_time(hour_bin, "%d/%m/%Y %H:%M")
  )

ggplot(df) +
  geom_point(aes(x = hour_bin, y = mean_calling_activity)) +
  scale_x_datetime(date_breaks = "1 hour", date_labels = "%H") +
  guides(
    x = guide_axis_nested(
      key = key_range_manual(
        start = c(
          lubridate::parse_date_time("05/02/2025 21:00", "%d/%m/%Y %H:%M"),
          lubridate::parse_date_time("06/02/2025 21:00", "%d/%m/%Y %H:%M")
        ),
        end = c(
          lubridate::parse_date_time("06/02/2025 05:00", "%d/%m/%Y %H:%M"),
          lubridate::parse_date_time("07/02/2025 05:00", "%d/%m/%Y %H:%M")
        ),
        name = c("First Night", "Second Night")
      ),
      bracket = "square"
    )
  )

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.