Search code examples
rggplot2polar-coordinates

how to plot year clock chart that resembles the ones by rhythm of food


I have the following data, which is just a part of more than 20,000 rows of data (you can import it into r by copying the following data and then run read.delim("clipboard",sep = ",")):

  "datetime","speed","month_name","year"
2011-01-01 01:00:00,10.14,"Jan",2011
2011-01-01 02:00:00,10.12,"Jan",2011
2011-01-01 03:00:00,8.94,"Jan",2011
2011-01-01 04:00:00,9.53,"Jan",2011
2011-01-01 05:00:00,11.68,"Jan",2011
2011-01-01 06:00:00,10.93,"Jan",2011
2011-01-01 07:00:00,11.01,"Jan",2011
2011-01-01 08:00:00,11.56,"Jan",2011
2011-01-01 09:00:00,10.47,"Jan",2011
2011-01-01 10:00:00,11.18,"Jan",2011
2011-01-01 11:00:00,10.82,"Jan",2011
2011-01-01 12:00:00,10.91,"Jan",2011
2011-01-01 13:00:00,11,"Jan",2011
2011-01-01 14:00:00,11.06,"Jan",2011
2011-01-01 15:00:00,11.95,"Jan",2011
2011-01-01 16:00:00,10.85,"Jan",2011
2011-01-01 17:00:00,11.22,"Jan",2011
2011-01-01 18:00:00,10.2,"Jan",2011
2011-01-01 19:00:00,11.43,"Jan",2011
2011-01-01 20:00:00,10.62,"Jan",2011
2011-01-01 21:00:00,10.26,"Jan",2011
2011-01-01 22:00:00,10.11,"Jan",2011
2011-01-01 23:00:00,9.81,"Jan",2011
2011-01-02 00:00:00,9.21,"Jan",2011
2011-01-02 01:00:00,8.7,"Jan",2011
2011-01-02 02:00:00,8.23,"Jan",2011
2011-01-02 03:00:00,8.98,"Jan",2011
2011-01-02 04:00:00,9.34,"Jan",2011
2011-01-02 05:00:00,8.57,"Jan",2011
2011-01-02 06:00:00,9.03,"Jan",2011

I would like to create a clock chart similar to the picture below, which is from google rhythm of food : enter image description here

Here is my code and the output, which produces something completely different:

df %>% ggplot(aes(x = month_name,  y = speed)) +
  geom_bar(stat="identity", width = 0.5) +  
  coord_polar(start=0)

enter image description here

I want the radius of the circle to be the speed and the colour to be the frequency of that speed. similar to the following figure, but instead of directions, I want to have months around the circle the same as the first figure.

enter image description here

The code here doesn't work.


Solution

  • Your sample data isn't adequate to give a demonstration, so let's recreate a data set that has 3 years worth of hourly readings (which your own seems to have). The only variables we need are speed and datetime:

    library(tidyverse)
    
    set.seed(82)
    
    df <- data.frame(datetime = seq(as.POSIXct("2011-01-01"), 
                                    as.POSIXct("2014-01-01"), by = "hour"),
                     speed = abs(cumsum(rnorm(26305)))/2)
    
    df %>%
      mutate(week  = lubridate::week(datetime),
             speed = cut(speed, breaks = seq(0, 40, 5)),
             speed = gsub("\\[|\\]|\\(|\\)", "", speed),
             speed = sapply(strsplit(speed, ","), 
                            function(x) mean(as.numeric(x)))) %>%
      count(week, speed) %>%
      ggplot(aes(x = week, y = speed)) +
      geom_point(data = expand.grid(week = 0:52 + 0.5, speed = seq(5, 40, 5)),
                 color = "gray", size = 0.5) +
      geom_tile(aes(fill = n), width = 0.8, height = 4.5) +
      geomtextpath::geom_textsegment(
        data = data.frame(x = seq(0.5, 49.5, 52/12),
                          xend = seq(0.5, 49.5, 52/12) + 4,
                          label = toupper(month.abb)),
        inherit.aes = FALSE, color = "grey", vjust = -0.4, size = 8,
        aes(x = x, xend = xend, label = label, y = 45, yend = 45)) +
      coord_polar() +
      scale_fill_viridis_c(name = "Frequency") +
      scale_y_continuous(breaks = seq(0, 40, 5), limits = c(-10, 50)) +
      theme(panel.background = element_blank(),
            axis.text.x = element_blank(),
            axis.title.y = element_text(size = 16, hjust = 0.75),
            axis.title.x = element_blank(),
            legend.direction = "horizontal",
            legend.position = c(0.1, 0.1),
            legend.title = element_text(size = 16, vjust = 0.75))
    

    enter image description here

    Created on 2022-08-14 by the reprex package (v2.0.1)