Spiral barplot using ggplot & coord_polar (Condegram)

前端 未结 1 1919
旧时难觅i
旧时难觅i 2021-01-04 10:35

I\'d like to create a bar plot on an Archimedean spiral, like discussed here.

With an end goal of something like this, but less overwhelming.

Here\'s a sampl

相关标签:
1条回答
  • 2021-01-04 11:24

    A fun question. To do this properly with bars, we need to use polygons to correctly account for the 'warp' of each corner. This plot will look better the more bars per cycle you have, but you can change the y limits to avoid strong distortion in the center. You'll have to come up with some way to nicely label the y-axis, but coord_polar isn't very good at that to begin with.

    library(tidyverse)
    

    First, either create sample df from scratch:

    monthly <- 
      expand.grid(month = 1:12, year = factor(unique(monthly$year))) %>% 
      mutate(value = runif(n(), 10, 20),
             y = as.numeric(year) - 1 + (month - 1) / 12) 
    

    Or, working from an existing df:

        monthly <- monthly %>%
          mutate(y = as.numeric(year) - 1 + (month - 1) / 12)
    

    Continue with the following:

    bars <- monthly %>% 
      mutate(value_norm = value / (max(value) * 1.1),
             xmin = month - 0.5,
             xmax = month + 0.5,
             ymin = y,
             ymax = y + value_norm)
    # we could plot `bars` here, but things will not line up nicely, since
    # the bar will be nice and flat, but it needs to curve with the spiral.
    
    poly <- bars %>% 
      rowwise() %>% 
      do(with(., data_frame(year = year,
                            month = month,
                            x = c(xmin, xmax, xmax, xmin),
                            y = c(ymin - 1/24, 
                                  ymin + 1/24, 
                                  ymax + 1/24, 
                                  ymax - 1/24))))
    
    ggplot(poly, aes(x, y, fill = interaction(month, year))) + 
      geom_polygon(col = 1) +
      coord_polar() +
      ylim(-3, 5) +
      viridis::scale_fill_viridis(discrete = TRUE, option = 'C') +
      scale_x_continuous(breaks = 1:12, labels = month.name) +
      theme_minimal() + 
      theme(legend.position = "none", axis.text.y = element_blank(),
            axis.title = element_blank())
    

    An alternative is to just make a spiralling heatmap:

    bars2 <- monthly %>% 
      mutate(xmin = month - 0.5,
             xmax = month + 0.5,
             ymin = y,
             ymax = y + 1)
    
    poly2 <- bars2 %>% 
      rowwise() %>% 
      do(with(., data_frame(value = value,
                            year = year,
                            month = month,
                            x = c(xmin, xmax, xmax, xmin),
                            y = c(ymin - 1/24, ymin + 1/24, ymax + 1/24, ymax - 1/24))))
    

    0 讨论(0)
提交回复
热议问题