Circular bar chart (incl. automated search)

Macrobond R API is available for users with Data+ and Legacy license (the latter without searching and revision history functions). Examples were tested on Macrobond version 1.27, Macrobond API for R version 1.2-8 and R 4.4.0.

The first method uses 'search by concept' to find whole data set based on one series. Example is presented on Annual Hours Worked per Worker data from Conference Board TED.

 

Circular Bar chart method 1 created with ggplot2 package (click to enlarge). Search query is based on concept metadata. You only need code for one series and the rest is downloaded automatically. Jump to the code.

Circular Bar chart method 2 created with ggplot2 package. In this example codes are loaded manually. Jump to the code.

With 'search by concept'

library(MacrobondAPI)
library(ggplot2)
library(tidyverse)
library(countrycode)

#choose series
series<-FetchOneTimeSeries("ted_ar_ahw")
#get the concept of a series and create search query based on it
query <- CreateSearchQuery() 
setEntityTypeFilter(query, "TimeSeries") 
addAttributeValueFilter(query, "RegionKey", getConcepts(series)) 
country_set <- getEntities(SearchEntities(query))

#create empty vectors
list_of_series<-NULL
values<-NULL
country<-NULL

#get list of series' codes
for (i in country_set){
  list_of_series<-append(list_of_series, getName(i))
}

#get last values 
for (i in list_of_series){
  values<-append(values, last(getValues(FetchOneTimeSeries(i))))
}

#get export countries ISO codes
for (i in list_of_series){
  country<-append(country, getMetadataValues(getMetadata(FetchOneTimeSeries(i)), "Region"))
}

#change ISO codes to names
country<-countrycode(as.vector(country), origin="iso2c", destination ="country.name")

#prepare data frame
data <- data.frame(values, country) %>%
  drop_na() %>% #remove NA, useful when data set has series for group of countries
  arrange(values) %>% #this will sort data frame only
  mutate(country=factor(country, levels=country)) #for ggplot2 you need to plot factor levels too
data <- mutate(data, id=seq(from=1, to=nrow(data)))

#prepare labels data
label_data <- data

#calculate the ANGLE of the labels
number_of_bar <- nrow(label_data)
#subtract 0.5 because the letter must have the angle of the center of the bars. Not extreme right(1) or extreme left (0)
angle <-  90 - 360 * (label_data$id-0.5) /number_of_bar 

#calculate the alignment of labels: right or left
label_data$hjust<-ifelse(angle < -90, 1, 0)
#flip angle 'by' to make them readable
label_data$angle<-ifelse(angle < -90, angle+180, angle)

#chart
p <- ggplot(label_data, aes(x=country, y=values)) + 
  geom_bar(stat="identity", fill=alpha("#9054a5",1)) + #select color
  ylim(-800,3000)+
  coord_polar(start = 0)+
  theme_minimal() +
  theme(
    axis.text = element_blank(),
    axis.title = element_blank(),
    panel.grid = element_blank(),
    plot.margin = unit(rep(-1,4), "cm") 
  )+
  geom_text(data=label_data, aes(x=id, y=values+5, label=country, hjust=hjust), 
            color="black", family="Helvetica", fontface="bold",alpha=1, size=1.7, angle= label_data$angle, inherit.aes = FALSE)+ #add country labels
  geom_text(data=label_data, aes(x=id, y=(-100), label=round(values,0), hjust=hjust), 
            color="black", family="Helvetica",alpha=1, size=1, angle=label_data$angle, inherit.aes = FALSE) #add value labels

#add title
p + ggtitle("Annual Hours Worked per Worker")+
  theme(plot.title = element_text(face="bold", size=12, hjust = 0.5))

With manual download

library(MacrobondAPI)
library(ggplot2)
library(tidyverse)
library(countrycode)

#add series
list_of_series<-c("ted_ar_ahw", "ted_au_ahw", "ted_at_ahw", "ted_bd_ahw", "ted_be_ahw", "ted_br_ahw", "ted_bg_ahw", "ted_kh_ahw", "ted_ca_ahw", "ted_cl_ahw", "ted_co_ahw", "ted_cr_ahw", "ted_hr_ahw", "ted_cy_ahw", "ted_cz_ahw", "ted_dk_ahw", "ted_ec_ahw", "ted_ee_ahw", "ted_fi_ahw", "ted_fr_ahw", "ted_de_ahw", "ted_gr_ahw", "ted_hk_ahw", "ted_hu_ahw", "ted_is_ahw", "ted_id_ahw", "ted_ie_ahw", "ted_il_ahw", "ted_it_ahw", "ted_jm_ahw", "ted_jp_ahw", "ted_lv_ahw", "ted_lt_ahw", "ted_lu_ahw", "ted_my_ahw", "ted_mt_ahw", "ted_mx_ahw", "ted_nl_ahw", "ted_nz_ahw", "ted_ng_ahw", "ted_no_ahw", "ted_pk_ahw", "ted_pe_ahw", "ted_ph_ahw", "ted_pl_ahw", "ted_pt_ahw", "ted_ro_ahw", "ted_ru_ahw", "ted_sg_ahw", "ted_sk_ahw", "ted_si_ahw", "ted_za_ahw", "ted_kr_ahw", "ted_es_ahw", "ted_lk_ahw", "ted_se_ahw", "ted_ch_ahw", "ted_tw_ahw", "ted_th_ahw", "ted_tt_ahw", "ted_tr_ahw", "ted_gb_ahw", "ted_us_ahw", "ted_uy_ahw", "ted_ve_ahw", "ted_vn_ahw")

#create empty vectors
values<-NULL
country<-NULL

#get last values 
for (i in list_of_series){
  values<-append(values, last(getValues(FetchOneTimeSeries(i))))
}

#get countries ISO codes
for (i in list_of_series){
  country<-append(country, getMetadataValues(getMetadata(FetchOneTimeSeries(i)), "Region"))
}

#change ISO codes to names
country<-countrycode(as.vector(country), origin="iso2c", destination ="country.name")

#prepare data frame
data <- data.frame(values, country) %>%
  arrange(values) %>% #this will sort data frame only
  mutate(country=factor(country, levels=country)) #for ggplot2 you need to plot factor levels too
data <- mutate(data, id=seq(from=1, to=nrow(data)))

#prepare labels data
label_data <- data

#calculate the ANGLE of the labels
number_of_bar <- nrow(label_data)
#subtract 0.5 because the letter must have the angle of the center of the bars. Not extreme right(1) or extreme left (0)
angle <-  90 - 360 * (label_data$id-0.5) /number_of_bar 

#calculate the alignment of labels: right or left
label_data$hjust<-ifelse(angle < -90, 1, 0)
#flip angle BY to make them readable
label_data$angle<-ifelse(angle < -90, angle+180, angle)

#chart
p <- ggplot(label_data, aes(x=country, y=values)) + 
  geom_bar(stat="identity", fill=alpha("#9054a5",1)) + #select color
  ylim(-800,3000)+
  coord_polar(start = 0)+
  theme_minimal() +
  theme(
    axis.text = element_blank(),
    axis.title = element_blank(),
    panel.grid = element_blank(),
    plot.margin = unit(rep(-1,4), "cm") 
  )+
  geom_text(data=label_data, aes(x=id, y=values+5, label=country, hjust=hjust), 
            color="black", family="Helvetica", fontface="bold",alpha=1, size=1.7, angle= label_data$angle, inherit.aes = FALSE)+ #add country labels
  geom_text(data=label_data, aes(x=id, y=(-100), label=round(values,0), hjust=hjust), 
            color="black", family="Helvetica",alpha=1, size=1, angle=label_data$angle, inherit.aes = FALSE) #add value labels

#add title
p + ggtitle("Annual Hours Worked per Worker")+
  theme(plot.title = element_text(face="bold", size=12, hjust = 0.5))