Home > database >  How to recreate a line plot
How to recreate a line plot

Time:04-11

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?enter image description here

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())

enter image description here

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")

enter image description here

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()
  • Related