/
day03-polygons-football-clubs.R
143 lines (124 loc) · 6.13 KB
/
day03-polygons-football-clubs.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#' INSPIRATION: https://github.com/VictimOfMaths/30DayMapChallenge/blob/main/Day3_Polygons.R
#' Colin Angus
pacman::p_load("tidyverse", "here", "glue", "ggtext", "colorspace",
"sf", "osmdata", "paletteer", "rvest", "jsonlite")
## GEOMETRIES ==================================================================
## Area of Cologne
cgn_polygon <- getbb("Cologne, Germany", format_out = "sf_polygon")
st_crs(cgn_polygon) <- "EPSG:4326"
#' Football clubs in Cologne
#' https://de.wikipedia.org/wiki/Kategorie:Fu%C3%9Fballverein_aus_K%C3%B6ln
page <- read_html("https://de.wikipedia.org/wiki/Kategorie:Fu%C3%9Fballverein_aus_K%C3%B6ln")
clubs <- html_nodes(page, "div.mw-category ul a") %>%
html_text()
clubs
# Limit to clubs down to Oberliga (5th division)
clubs_1to5div <- c("1. FC Köln",
"SV Deutz 05",
"FC Junkersdorf",
"FC Pesch",
"SC Fortuna Köln",
"FC Viktoria Köln")
#' Football grounds
#' Search on Google Maps
grounds <- tibble(
club = clubs_1to5div,
ground = c("RheinEnergie Stadion",
"BB Bank Sportpark",
"Ostkampfbahn",
"Helmut-Kusserow-Sportanlage",
"Südstadion",
"Sportpark Höhenberg"),
coordinates = st_sfc(
st_point(c(6.875, 50.933611)),
st_point(c(6.9791233, 50.9259744)),
st_point(c(6.8755043, 50.933527)),
st_point(c(6.8688709, 51.001883)),
st_point(c(6.94361, 50.9175)),
st_point(c(7.03039, 50.9452))
),
club_icon = c(
here("data", "Emblem_1.FC_Köln.svg"),
here("data", "Logo_Deutz_05.svg"),
here("data", "LOGO_FC_Junkersdorf.svg"),
here("data", "FC_Pesch_Logo.svg"),
here("data", "SC_Fortuna_Koeln_Logo_since_2019.svg"),
here("data", "FC_Viktoria_Köln_1904_Logo.svg")
)
) %>%
st_as_sf(crs = 4326)
grounds2 <- grounds %>%
# exclude FC Junkersdorf which uses a ground at Sportpark Müngersdorf (1. FC Köln)
filter(club != "FC Junkersdorf")
#' Club icons
#' Attributions:
#' Viktoria Köln: Von FC Viktoria Köln 1904 e.V. - Extracted from PDF [1] and converted to SVG, Gemeinfrei, https://commons.wikimedia.org/w/index.php?curid=85249908
#' 1. FC Köln: Von Autor unbekannt - https://fc.de/typo3conf/ext/bra_projectfiles/Resources/Public/vorschaltseite/img/svg/01-logo.svg, Gemeinfrei, https://commons.wikimedia.org/w/index.php?curid=99279386
#' SV Deutz 05: Von Sportvereinigung Deutz 05 e. V. - vectorized from Sportvereinigung Deutz 05 e. V.-Website [1], Gemeinfrei, https://commons.wikimedia.org/w/index.php?curid=85273833
#' Fortuna Köln: Von S.C. Fortuna Köln e.V. - S.C. Fortuna Köln e.V. - SVG extracted from [1], Gemeinfrei, https://commons.wikimedia.org/w/index.php?curid=86903779
#' FC Pesch: Von FC Pesch 1956 e.V. - FC Pesch 1956 e.V., Gemeinfrei, https://commons.wikimedia.org/w/index.php?curid=86282215
#' FC Junkersdorf: Von FC Junkersdorf 1946 e.V. - FC Junkersdorf 1946 e.V., Gemeinfrei, https://commons.wikimedia.org/w/index.php?curid=85519922
## VORONOI TESSELATION =========================================================
# Create Voronoi cells based on club grounds
voronoi <- grounds2 %>%
st_union() %>%
st_voronoi() %>%
st_collection_extract()
# intersect with Cologne shape
voronoi <- voronoi[unlist(st_intersects(grounds2, voronoi))] %>%
st_intersection(cgn_polygon)
## PLOT ========================================================================
seed <- 4711
set.seed(seed)
p <- voronoi %>%
ggplot() +
geom_sf(aes(fill = sample(grounds2$club, size = nrow(grounds2), replace = FALSE)),
col = "white", size = 0.5, show.legend = FALSE) +
geom_sf(data = grounds2,
aes(geometry = coordinates), size = 3,
shape = 21, col = "white", fill = "grey12") +
ggimage::geom_image(data = grounds2,
aes(x = st_coordinates(coordinates)[, "X"],
y = st_coordinates(coordinates)[, "Y"],
image = club_icon),
inherit.aes = FALSE) +
geom_sf_label(data = grounds2,
aes(geometry = coordinates, label = club),
size = 3, label.size = 0, label.r = unit(0.05, "lines"),
fill = "grey12", col = "white", alpha = 0.6,
hjust = 0, nudge_x = 0.012, nudge_y = -0.005,
family = "Chivo") +
scale_fill_paletteer_d("cartography::green.pal", dynamic = TRUE) +
labs(
# title = "Support your local club",
title = "Mer stonn zo dir, FC Kölle<sup>*</sup>",
subtitle = "Nearest (semi)-professional football teams' grounds to every point in Cologne",
caption = "<sup>\\*</sup><i>Translation:</i> We stand by you, FC Kölle.<br><br>
Data: **OpenStreetMap** | Visualization: **Ansgar Wolsing** |
Images credits: Wikipedia, the respective clubs") +
cowplot::theme_map() +
theme(plot.background = element_rect(color = NA, fill = "#1D1D59"),
text = element_text(family = "Roboto Light", color = "white"),
plot.title = element_markdown(family = "Roboto", size = 28,
margin = margin(b = 18)),
plot.subtitle = element_textbox_simple(size = 14),
plot.caption = element_textbox_simple(size = 9)
)
set.seed(seed)
ggsave(here("plots/day03_polygons_football_grounds.png"),
plot = p, dpi = 600, width = 8, height = 8)
# Adding an annotation for the missing FC Junkersdorf
coords_junkersdorf <- grounds$coordinates[grounds$club == "FC Junkersdorf"]
lat_junkersdorf <- st_coordinates(coords_junkersdorf)[, "X"]
lon_junkersdorf <- st_coordinates(coords_junkersdorf)[, "YY"]
p +
ggimage::geom_image(aes(x = lat_junkersdorf - 0.095,
y = lon_junkersdorf - 0.05,
image = grounds$club_icon[grounds$club == "FC Junkersdorf"]),
inherit.aes = FALSE) +
geom_textbox(x = lat_junkersdorf - 0.095, y = lon_junkersdorf -0.05,
label = "FC Junkersdorf (5th division)",
width = unit(50, "mm"), fill = NA, box.color = NA, hjust = 0,
family = "Roboto", color = "white", size = 3.5)
ggsave(here("plots/day03_polygons_football_grounds_w_junkersdorf.png"),
dpi = 600, width = 8, height = 8)