Home > Mobile >  In R ggplot , a few questions about 'geom_rect' with polar coordinates
In R ggplot , a few questions about 'geom_rect' with polar coordinates

Time:10-27

In R ggplot , using 'geom_rect' can generate below plot. Now, I have a few questions :

  1. Is there any way to simplify current code ?
  2. How to add 'amount' to the label (currently, it's only include 'category/sub_category')
  3. The 'fill color' is ugly , especially for the 'sub_category' (maybe using same colors ,just change the 'alpha' parameter)
  4. the boarder isn’t very smooth (jagged border)

Anyone can help ? Thanks!

   library(tidyverse)
    
    test_data <- data.frame(category = c("retail","retail","retail","retail","retail","hotel"),
                            sub_category=c("retail_sub1","retail_sub2","retail_sub3","retail_sub4","retail_sub5","hotel"),
                          amount=c(51083.26,27454.13,22495.89,21195.05,16863.69,60210.6))
    
    test_data1 <- test_data %>% mutate(ymax=cumsum(amount),
                         ymin=lag(cumsum(amount),default=0))
    
    
    test_data1$y_category_position[test_data1$category=='retail'] <- 
      max(test_data1$ymax[test_data1$category=='retail'])/2
    
    
    test_data1$y_category_position[test_data1$category=='hotel'] <- 
      max(test_data1$ymax[test_data1$category=='retail']) 
      max(test_data1$ymax[test_data1$category=='hotel'])/6 # tried may times, seems 6 for divisor is better 
    
      test_data1 %>% ggplot() 
      # for category bar and label
      geom_rect(aes(xmin=3,xmax=6,ymin=ymin,ymax=ymax,fill=category)) 
      geom_text(aes(x=4.5,y=y_category_position,label=category)) 
      # for sub_category bar and label (exclude category 'hotel')
      geom_rect(data= test_data1 %>% filter(sub_category !='hotel'),
                aes(xmin=6,xmax=8,
                    ymin=ymin,ymax=ymax,fill=sub_category)) 
     geom_text(data= test_data1 %>% filter(sub_category !='hotel'),
               aes(x=7,y=(ymax ymin)/2,label=sub_category)) 
      coord_polar(theta = 'y') 
      theme_minimal()

enter image description here

CodePudding user response:

In the future, please ask 1 question per post.

To answer your questions point by point.

  1. Can this code be simplified?

Yes, you essentially have a stacked bar chart, so if we want 1 label per area we need to pre-summarise the data, but needn't bother with precalculating cumsums and such.

library(tidyverse)

test_data <- data.frame(category = c("retail","retail","retail","retail","retail","hotel"),
                        sub_category=c("retail_sub1","retail_sub2","retail_sub3","retail_sub4","retail_sub5","hotel"),
                        amount=c(51083.26,27454.13,22495.89,21195.05,16863.69,60210.6))

barchart <- test_data %>%
  # Reshape data
  pivot_longer(-amount, names_to = "level", values_to = "name") %>%
  # Filter out the hotel subcategory, leaving in the (super)category
  filter(!(level == "sub_category" & name == "hotel")) %>%
  # Sum over category level and names
  group_by(level, name) %>%
  summarise(amount = sum(amount), .groups = "keep") %>%
  # Regular stacked bar chart code
  ggplot(aes(x = level, y = amount))  
  geom_col(aes(fill = name), width = 1)  
  geom_text(
    aes(label = paste0(name, "\n", amount), # <--- point 2
        group = interaction(name, level)),
    position = position_stack(vjust = 0.5),
  )
barchart

Subsequently, adding coord_polar() will make the barchart in the donut chart.

barchart   coord_polar(theta = "y")

Created on 2021-10-26 by the reprex package (v2.0.1)

  1. How to add 'amount' to the label?

You can just set label = paste0(name, "\n", amount) as an aesthetic (see code).

  1. The 'fill color' is ugly.

Look into the scale_fill_*() family of functions for discrete palettes.

  1. The border isn’t very smooth.

That depends on the anti-aliasing for your graphics device. In RStudio you can set 'Tools > Global Options > General > Graphics > Backend > Select AGG' (or Cairo). For saving plots you could for example use ragg::agg_png().

  • Related