How to create equal distance between discrete categories with different numbers per facet, using facet_wrap

Viewed 138

My aim is to have more or less equal distance between all the countries in the plot. For example, in the first category (Increase), the countries are dispersed. On the other hand, the countries in the second and third category are too close to each other.

This forces me to decrease the size of the text of the countries (e.g., "IS", "UK"...) and the estimates that are plotted (e.g., "1.5", "1.2"...). Thus once I extract this file to pdf or word, the reader cannot see clearly what are the names of the countries or the estimates. If i increase their size text, then the countries overlap and some estimates (especially the ones of the Stable category) touch the other estimates next to them.

Is there a way to get around this problem?

enter image description here

Here is the data and the code:

structure(list(cntry = structure(1:26, .Label = c("AU", "BE", 
"BG", "CY", "CZ", "DK", "EE", "GR", "ES", "FI", "FR", "HU", "IE", 
"IS", "IT", "LT", "LV", "NL", "NO", "PO", "PT", "RO", "SE", "SV", 
"SK", "UK"), class = "factor"), estimate = c(-4.08943257103804, 
0.264307961887035, -0.4008773217117, -1.91874959282838, -0.964527079847473, 
-4.30067253169461, -0.920426011686486, -0.0746109649703081, 1.03855028529355, 
-1.28691260252507, -3.21446990383498, -0.0381504621278269, 0.0286675062078212, 
1.46814093121697, -0.50165518722767, -0.787733440190981, 0.745627449639574, 
0.586929625060384, 0.191285070657763, 0.217512744502688, 1.35842665232147, 
0.358385446150237, -0.238203754070039, -1.59896322663246, 0.100424706108376, 
1.15585740391863), conf.low = c(-5.60117192484885, -0.840219073796263, 
-1.62699620711119, -3.64218275679053, -2.0989086744086, -6.58558173414225, 
-2.11216930433376, -0.986944473894656, 0.221565068594325, -2.69498298777435, 
-3.98554432677659, -1.10463119017979, -1.86828501326683, -1.18099254843252, 
-1.27464693464705, -2.24155213350216, -0.522730236481673, -0.479328474807381, 
-1.20651423960493, -0.461478316905123, -2.34340124131767, -0.458919023509462, 
-1.65550186084418, -3.35325169024894, -1.17499651445811, 0.0527941744160207
), conf.high = c(-2.57769321722723, 1.36883499757033, 0.825241563687791, 
-0.195316428866239, 0.169854514713651, -2.01576332924696, 0.271317280960783, 
0.83772254395404, 1.85553550199278, 0.121157782724206, -2.44339548089336, 
1.02833026592413, 1.92562002568248, 4.11727441086645, 0.271336560191708, 
0.666085253120201, 2.01398513576082, 1.65318772492815, 1.58908438092046, 
0.8965038059105, 5.0602545459606, 1.17568991580994, 1.1790943527041, 
0.155325236984016, 1.37584592667486, 2.25892063342124), crisis_f = structure(c(3L, 
2L, 2L, 3L, 3L, 3L, 3L, 2L, 1L, 3L, 3L, 2L, 2L, 1L, 3L, 3L, 1L, 
1L, 2L, 2L, 2L, 2L, 2L, 3L, 2L, 1L), .Label = c("Increase", "Stable", 
"Decrease"), class = "factor")), row.names = c(NA, -26L), class = "data.frame")

library(ggplot2)
library(dplyr)
library(forcats)

df %>%
  arrange(estimate) %>%
  mutate(label = replace(round(estimate, 1),cntry==1, '')) %>%
  ggplot(aes(x= estimate, fct_reorder(cntry, estimate, .desc = TRUE),label=label)) +
  geom_point()+
  geom_text(hjust= -0.5, size=2.5)  + 
  geom_linerange(mapping=aes(xmin=conf.low , xmax=conf.high, y=cntry), width=0.1, size=.5, color="black") + 
  geom_point(mapping=aes(x=estimate, y=cntry), size=2.3, shape=21, fill="black") +
  geom_vline(xintercept=0, color = "black", linetype= "dotted") +
  ggtitle(NULL) + xlab("Happiness") + 
  scale_y_discrete(expand = expansion(add = 1)) +
  facet_wrap(vars(crisis_f), scales = "free_x", strip.position = "bottom", shrink=F) +
  ylab("")   +
  theme_classic() +
  theme( 
    plot.title = element_text(color="Black", size=24, face="bold", hjust= 0.5), axis.title.x = element_text(color="Black", size=24, face="bold"),
    axis.title.y = element_text(color="Black", size=20, face="bold"),
    axis.text.x = element_text(color="black", size=10),
    axis.text.y = element_text(face="bold", color="black", size=14),
    strip.text = element_text(face= "bold", size=17),
    plot.caption = element_text(size= 12),
    legend.justification=c(1,0),
    legend.position=c(1,0),
    strip.placement = "outside",
    strip.background = element_rect(line = "solid"),
    panel.spacing = unit(0, "mm")) + 
  coord_flip() 
1 Answers

You could use facet_row from ggforce which allows free scales and strip.position='bottom':

library(ggplot2)
library(dplyr)
library(forcats)
library(ggforce)

p <- df %>%
  arrange(estimate) %>%
  mutate(label = replace(round(estimate, 1),cntry==1, '')) %>%
  ggplot(aes(x= estimate, fct_reorder(cntry, estimate, .desc = TRUE),label=label)) +
  geom_point()+
  geom_text(hjust= -0.5, size=2.5)  + 
  geom_linerange(mapping=aes(xmin=conf.low , xmax=conf.high, y=cntry), width=0.1, size=.5, color="black") + 
  geom_point(mapping=aes(x=estimate, y=cntry), size=2.3, shape=21, fill="black") +
  geom_vline(xintercept=0, color = "black", linetype= "dotted") +
  ggtitle(NULL) + xlab("Happiness") + 
  scale_y_discrete(expand = expansion(add = 1)) +
  ylab("")   +
  theme_classic() +
  theme( 
    plot.title = element_text(color="Black", size=24, face="bold", hjust= 0.5), axis.title.x = element_text(color="Black", size=24, face="bold"),
    axis.title.y = element_text(color="Black", size=20, face="bold"),
    axis.text.x = element_text(color="black", size=10),
    axis.text.y = element_text(face="bold", color="black", size=14),
    strip.text = element_text(face= "bold", size=17),
    plot.caption = element_text(size= 12),
    legend.justification=c(1,0),
    legend.position=c(1,0),
    strip.placement = "outside",
    strip.background = element_rect(line = "solid"),
    panel.spacing = unit(0, "mm")) + 
  coord_flip() 

p + ggforce::facet_row(vars(crisis_f), scales = 'free_x', space = 'free',strip.position = 'bottom')

enter image description here

Related