I'm trying to plot the GDP for every country on a bar chart. The country name goes on the x-axis and the GDP value on the y. However, there are a lot of countries, and I'd like the bar chart to just show the top 3 GDPs, and the bottom 3 GDPs and in between I want perhaps some dots or something to indicate that there are other countries in between. How do I go about this?
2 Answers
Building on @steveLangsford's solution - doing things in a (possibly) slightly more principled way
There might be a more "tidy" way to do this part:
- find breakpoints for GDP categories:
GDP_sorted <- sort(toydata$GDP)
GDP_breaks <- c(-Inf,GDP_sorted[hm_selected],
GDP_sorted[hm_rows-hm_selected],
Inf)
- use
cut()
to define GDP categories, and order countries by GDP:
toydata <- toydata %>%
mutate(GDP_cat=cut(GDP,breaks=GDP_breaks,labels=
c("Lowest","Mid","Highest")),
country=reorder(factor(country),GDP)) %>%
filter(GDP_cat != "Mid") %>%
droplevels()
Plot with facets (add a bit of extra space between the panels to emphasize the axis break):
ggplot(toydata,aes(x=country,y=GDP,fill=GDP_cat))+
geom_bar(stat="identity")+
theme_bw()+
theme(legend.position="none",
panel.spacing.x=grid::unit(5,"lines")
)+xlab("")+
scale_fill_brewer(palette="Dark2")+
facet_wrap(~GDP_cat,scale="free_x")

- 211,554
- 25
- 370
- 453
1) You will get faster better answers if you give a toy data set
2) Putting "dots or something" on your plot is likely to make data visualization people wince a little. You're basically suggesting a discontinuity in the x-axis, which is a common enough thing to do, but specifically excluded from ggplot
(see here:
Using ggplot2, can I insert a break in the axis?
and here:
https://groups.google.com/forum/#!topic/ggplot2/jSrL_FnS8kc)
But, this same discussion suggests facets as a solution to your problem. One way to do that might be something like this:
library(tidyverse)
library(patchwork)
hm_rows <- 50
hm_selected <- 3
toydata <- data.frame(country=paste("Country",1:hm_rows) ,GDP=runif(hm_rows,0,5000))%>%
arrange(desc(GDP))%>%
filter(row_number()<=hm_selected | row_number()>(hm_rows-hm_selected))%>%droplevels
toydata$status <- rep(c("Highest","Lowest"),each=hm_selected)
ggplot(toydata%>%filter(status=="Highest"),aes(x=country,y=GDP))+
geom_bar(stat="identity")+
ggtitle("Highest")+
ylim(c(0,max(toydata$GDP)))+
ggplot(toydata%>%filter(status=="Lowest"),aes(x=country,y=GDP))+
geom_bar(stat="identity")+
ggtitle("Lowest")+
ylim(c(0,max(toydata$GDP)))+
theme(#possibly questionable, but tweaks the results closer to the single-graph requested:
axis.text.y=element_blank(),
axis.ticks=element_blank()
)+ylab("")

- 646
- 5
- 9
-
1note `devtools::install_github("thomasp85/patchwork")` ... why are you using `patchwork` rather than ordinary faceting? – Ben Bolker Mar 11 '18 at 16:33
-
Ordinary faceting keeps the x-axis consistent across the facets. Patchwork let me have country A ,B, C for the x-axis in the left panel and country X, Y, Z on the right. There might be better ways but this was quickest/easiest for me. Thanks for commenting the github install, I forgot about that! – steveLangsford Mar 11 '18 at 16:45
-
See my solution (`scale=="free_x"`) – Ben Bolker Mar 11 '18 at 16:47
-
Oh, that is nice. Didn't know about that, thanks for pointing it out! – steveLangsford Mar 11 '18 at 16:54