rggplot2

Display polar histogram from 0 to 360 degrees using coord_polar() & geom_histogram()


I would like to create polar histograms that wrap around, however my code doesn't display anything for the 0 degree bin. I couldn't find anything in the documentation of coord_polar() that would let me do this, so I think the issue seem to be geom_histogram().

Here is a toy example:

angles   <- data.frame(x = rnorm(10000, mean = 270, sd = 75))
angles$x <- angles$x %% 360

ggplot(angles, aes(x = x)) +
  geom_histogram(binwidth = 15, colour = "black", size = .25) +
  scale_x_continuous(limits = c(0, 360),
                      breaks = seq(0, 360, by = 30),
                    minor_breaks = seq(0, 360, by = 15))  +
  # scale_y_continuous(limits = c(0, 500)) +
  coord_polar(start = 0) +
  theme(plot.title = element_text(hjust = 0.5)) + 
  labs(y = 'Count', x = '')

As you can see below there is no bin for 0/360.

enter image description here

Edit:

The suggestion to remove limits in scale_x_continuous() does make the plot wrap around but now 0 and 360 are separate.

angles <- data.frame(x = runif(10000, 0, 360))
angles$x  <- angles$x %% 360

ggplot(angles, aes(x = x)) +
  geom_histogram(binwidth = 15, colour = "black", size = .25) +
  scale_x_continuous(breaks = seq(0, 360, by = 30),
                     minor_breaks = seq(0, 360, by = 15))  +
  # scale_y_continuous(limits = c(0, 500)) +
  coord_polar(start = 0, clip = "off") +
  theme(plot.title = element_text(hjust = 0.5)) + 
  labs(y = 'Count', x = '')

enter image description here


Solution

  • When you make a histogram, your first and last bins, centred at 0 and 360, are separate:

    ggplot(angles, aes(x = x)) +
      geom_histogram(binwidth = 15, colour = "black", size = .25) +
      scale_x_continuous(breaks = seq(0, 360, by = 15),
                         labels=seq(0, 360, 15))
    

    enter image description here

    But then you want to force these extreme bins to coincide on the polar coordinate plot? If you want 0 and 360 to coincide, combine them first, then make the plot. The last bin will be centred at 345, so you want anything greater than 345+7.5 (half the bin width) to be replaced with 0 (or any number between 0 and 7.5).

    mutate(angles, x=ifelse(x>352.5, 0, x)) %>%
      ggplot(aes(x = x)) +
      geom_histogram(binwidth = 15, colour = "black", size = .25) +
      scale_x_continuous(breaks = seq(0, 330, by = 30),
                         labels=c("0/360", seq(30, 330, 30)),
                         minor_breaks = seq(0, 345, by = 15))  +
      coord_polar(start = -1/7.5) +  # half the bin width
      theme(plot.title = element_text(hjust = 0.5)) + 
      labs(y = 'Count', x = '')
    

    enter image description here