This is an awkward question, and I don't want to offend anyone. I'd like to recreate the following figure in R. The plot is based on a published work. I'm not sure what the backstory is. How should I proceed using ggplot?
CodePudding user response:
We can get arbitrarily close in ggplot as long as we are prepared to put the work into preparing the data.
Firstly, we need a data frame of the labels and the segment positions:
df <- data.frame(text = c('Africa', 'Asia', 'Countries in transition',
'North America', 'South America',
'Western Europe'),
y = 6:1,
x = c(0, 0, 1.5, 6.5, 0, 6),
xend = c(5, 6.5, 6, 10, 5, 10))
Secondly, we need the x axis labels:
xlabs <- c('early EIAs,\noften donor\nfunded',
'EIA regulation/guidance\nenacted, increasing EIAs\nquality variable',
'EIA mainstream,\nfine-tuning of\nregulation/guidance')
If you want the polka-dot background, it is possible to do this via ggpattern
, but if you want to stick to CRAN-based repositories, we can now use a pattern fill in grid
, which you already have installed. You will need to have the latest version of R installed to do this though:
library(grid)
small_circ1 <- circleGrob(
r = unit(0.5, 'mm'),
gp = gpar(fill = '#d4dbed', col = '#d4dbed')
)
small_circ2 <- circleGrob(
r = unit(0.5, 'mm'),
gp = gpar(fill = '#c5d0e5', col = '#c5d0e5')
)
small_circle_pattern1 <- pattern(
small_circ1,
width = unit(2.5, 'mm'),
height = unit(2.5, 'mm'),
extend = 'repeat'
)
small_circle_pattern2 <- pattern(
small_circ2,
width = unit(2.5, 'mm'),
height = unit(2.5, 'mm'),
extend = 'repeat'
)
Now we are ready to plot. The easiest way to get the broken line segments with text is using geom_textsegment
from geomtextpath
library(geomtextpath)
ggplot(df, aes(x, y))
annotation_custom(rectGrob(gp = gpar(fill = small_circle_pattern1,
col = NA)),
ymin = -Inf, ymax = Inf, xmin = 2, xmax = 6)
annotation_custom(rectGrob(gp = gpar(fill = '#e6e9f9', col = '#e6e9f9')),
ymin = -Inf, ymax = Inf, xmin = 6, xmax = 10)
annotation_custom(rectGrob(gp = gpar(fill = small_circle_pattern2,
col = NA)),
ymin = -Inf, ymax = Inf, xmin = 6, xmax = 10)
geom_textsegment(aes(yend = y, xend = xend, label = text, fontface = 2),
colour = '#556fa1', linewidth = 0.7, size = 5)
scale_x_continuous(breaks = c(0, 2, 6),
labels = xlabs, expand = c(0, 0))
theme_classic()
theme(axis.text.x = element_text(size = 14, hjust = 0,
margin = margin(20, 0, 0, 0),
colour = '#556fa1'),
axis.line = element_line(colour = '#556fa1'),
axis.ticks = element_blank(),
axis.text.y = element_blank(),
axis.title = element_blank())
CodePudding user response:
It remains unclear, how detailed the reproduction ought to be (same background or same in general=). It is also unclear, which graphics system you want to work in. Should you want to try that in base graphics, the following might provide you with a workable starting point:
dat <- data.frame(continent = c("Afrika", "Asia", "North America",
"South America", "Europe"),
from = c(0, 0, 6, 0, 5),
to = c(4, 5.5, 10, 5, 10))
dat$mean <- (dat$from dat$to) / 2
plot(NA, xlim = c(0, 10), ylim = c(0,6), xaxt = "n", yaxt = "n",
xlab = "", ylab = "")
for(i in 1:5){
print(c(dat$from[i], dat$to[i]))
lines(x = c(dat$from[i], dat$to[i]),
y = c(6-i, 6-i),
col = "lightblue", lwd = 2)
}
text(dat$mean, y = (5:1) .3, labels = dat$continent,
col = "lightblue")
CodePudding user response:
As a mere starting point on how to possibly approach the problem in ggplot2
:
dat <- data.frame(no = 1:5,
continent = c("Afrika", "Asia", "North America",
"South America", "Europe"),
from = c(0, 0, 6, 0, 5),
to = c(4, 5.5, 10, 5, 10))
library(ggplot2)
ggplot(dat)
geom_segment(aes(x = from, y = 6-no, xend = to, yend = 6-no), lwd = 2)
geom_text(aes(x = mean, y = 6.2-no, label = continent))
theme_bw()