
This is a work file - see the slides for the final code.
Copied from: https://www.jla-data.net/eng/minard-map-tidygeocoder/

```{r}
library(tidygeocoder)
library(ggplot2)
library(dplyr)

minard_raw <- data.frame(city = c("Kaunas", "Vilnius", "Глубокое", "Витебск", 
                                  "Смоленск", "Дорогобу́ж", "Гага́рин"  ,
                                  "Можа́йск",  "Москва", "Москва", 
                                  "Малояросла́вец", "Можа́йск", "Вя́зьма",
                                  "Дорогобу́ж", "Смоленск", "О́рша",
                                  "Бобр", "Бори́сов",  "Маладзечна",
                                  "Сморгонь", "Vilnius", "Kaunas", # La Grande Armée
                                  "Vilnius", "Daugavpils",  
                                  "По́лоцк", "Бобр", # reserve in Polotskt
                                  "Kaunas", "Riga", 
                                  "Riga", "Kaunas"), # the siege of Riga
                     direction = c("outward", "outward", "outward", "outward",
                                   "outward", "outward", "outward", "outward",
                                   "outward", "homeward", "homeward", "homeward",
                                   "homeward", "homeward", "homeward", "homeward",
                                   "homeward", "homeward", "homeward", "homeward",
                                   "homeward", "homeward", # Napoleon
                                   "outward", "outward", "homeward",
                                   "homeward", # Oudinot
                                   "outward", "outward", "homeward", 
                                   "homeward"), # MacDonald
                     strength = c(422000, 340000, 280000, 210000, 145000,
                                  140000, 127100, 100000, 100000, 100000,
                                  98000, 87000, 55000, 37000, 24000, 20000,
                                  50000, 28000, 12000, 14000, 8000,
                                  4000, # Napoleon
                                  60000, 40000, 33000, 28000, # Oudinot
                                  22000, 22000, 6000, 6000), # MacDonald
                     leader = c(rep("Napoleon", 22),  
                                rep("Oudinot", 4), 
                                rep("MacDonald", 4))) 
minard_raw
```

This call no longer returns data for several of the cities (see the NIL values returned).

```{r}
# let tidygeocoder perform its magic!
minard_geocoded <- minard_raw %>% 
  tidygeocoder::geocode(city = city, 
                        method = "osm") 
minard_geocoded
```

So I scraped his website data table.

```{r}
library(tidyverse)
minard_geocoded <- read_csv("data/menard-scraped-data.csv")
```

```{r}
knitr::kable(minard_geocoded,
             format.args = list(big.mark = ",",
                                scientific = FALSE))
```

```{r}
# city labels
city_labels <- minard_geocoded %>%
  select(city, lat, long) %>% 
  distinct()

# offsets - a kludge to make the labels legible
kludge <- data.frame(horizontal = c(0, -.25, -.2, 0, 0,
                                    .25, -.5, 0, 0, 0,
                                    .4, .25, .4, -.2, -.2,
                                    .7, -.25, .4, 0),
                     vertical = c(-.2, -.2, .3, .3, -.3,
                                  -.3, .2, .2, .2, -.2,
                                  -.3, -.2, -.15, .2, -.15,
                                  .1, .2, .2, .15))
```

```{r}
# and finally, the plot itself
ggplot() +
  # paths taken by the armies
  geom_path(data = minard_geocoded, 
            aes(x = long, 
                y = lat, 
                size = strength, 
                color = direction, 
                # make sure Napoleon gets drawn over Oudinot, not the other way round
                group = factor(leader, levels = c("Oudinot", 
                                                  "MacDonald",
                                                  "Napoleon")))) +
  # labels for the cities
  geom_text(data = city_labels,
            aes(x = long,
                y = lat,
                label = city),
            family = "Old Standard TT", # an old fashioned Cyrillic font
            fontface = "italic",
            # I wish that this was not necessary... 
            nudge_x = kludge$horizontal,
            nudge_y = kludge$vertical) +
  scale_colour_manual(values = c("gray10", 
                                 "#e8cbac")) + # the color Minard calls "rouge"
  scale_size(range = c(1/10, 17)) + # a "slight" exaggeration
  guides(color = F, size = F) + theme_void() + # just say "no" to distractions
  labs(title = "1812, or There and Back Again",
       subtitle = "geocoding the Minard's map") +
  theme(plot.title = element_text(hjust = 1/2,
                                  face = "bold"),
        plot.subtitle = element_text(hjust = 1/2,
                                     face = "italic"))
```

```{r}
library(ggmap)

# a basemap / consider maptype = "terrain-background" for an alternative look
basemap <- get_stamenmap(bbox = c(left =  23,
                                  bottom = 53.75,
                                  right = 39.25,
                                  top = 57.15),
                         maptype = "toner",
                         zoom = 7)

# the plot again, without text labels this time
ggmap(basemap) +
 geom_path(data = minard_geocoded, 
            aes(x = long, 
                y = lat, 
                size = strength, 
                color = direction, 
                group = factor(leader, levels = c("Oudinot", 
                                                  "MacDonald",
                                                  "Napoleon"))),
           alpha = 2/3) + # a slight alpha to retain a hint of the basemap
  scale_colour_manual(values = c("gray10", 
                                 "#e8cbac")) +
  scale_size(range = c(1/4, 17)) +
  guides(color = F, size = F) +
  theme_void() +
  labs(title = "1812, or There and Back Again",
       subtitle = "geocoding the Minard's map") +
  theme(plot.title = element_text(hjust = 1/2,
                                  face = "bold"),
        plot.subtitle = element_text(hjust = 1/2,
                                     face = "italic"))
```

```{r}
library(sf) 

# first make the data frame spatial object
sf_path <- minard_geocoded %>%  
  st_as_sf(coords = c("long", "lat"), crs = 4326) %>% 
  mutate(direction = as.factor(direction)) # factor for color palette assignment

minard_lines <- NULL # initiate an empty object
  
for (captain in unique(sf_path$leader)) { # i.e. Napoleon, Oudinot, MacDonald
  
  wrk_army <- subset(sf_path, leader == captain)

  # cycle over all segments, except the last one
  for (i in 1:(nrow(wrk_army)-1)) {
    
    # line object from two points
    wrk_line  <- wrk_army[c(i, i+1), ] %>% # current & next point coords
      st_coordinates() %>% 
      st_linestring() %>% 
      st_sfc()
    
    # a single row of results dataframe
    line_data <- data.frame(
      direction = wrk_army$direction[i],
      strength = wrk_army$strength[i],
      leader = wrk_army$leader[i],
      label = paste0(wrk_army$city[i], " to ",
                     wrk_army$city[i+1], "<br>army strength ",
                     format(wrk_army$strength[i], 
                            big.mark = ",",
                            scientific = F), " men."),
      geometry = wrk_line
    )
    
    # bind the single row to the output object
    if (is.null(minard_lines)) {
      
      minard_lines <- line_data
      
    } else {
      minard_lines <- dplyr::bind_rows(minard_lines,
                                       line_data)
      
    } # /if - binding results
    
  } # /for segment
  
} # /for leader

# finalize the linear object
minard_lines <- st_as_sf(minard_lines, crs = 4326)

library(leaflet)

# palette for direction
pal <- colorFactor(c("gray10", "#e8cbac"),
                   minard_lines$direction)

# the map itself
leaflet(data = minard_lines) %>% 
  addProviderTiles("Stamen.Toner") %>% 
  addPolylines(weight = ~strength/15000,
               color = ~pal(direction),
               opacity = 1,
               popup = ~label)
```