1

Import the ESRI shapefile of German districts and the district attribute table. Join the two data frames, transform the CRS to EPSG:3035, and check your changes.
You need to rename one of the id variables or adjust your join accordingly (AGS = district_id).
# load libraries
library(sf)
library(dplyr)

# Import data
german_districts <- 
  sf::read_sf("./data/VG250_KRS.shp") %>% 
  dplyr::mutate(district_id = as.numeric(AGS)) %>% 
  sf::st_transform(3035) %>% 
  dplyr::select(district_id,GEN)

attributes_districts <- readr::read_delim("./data/attributes_districts.csv",
                                          delim = ";") 
## Rows: 400 Columns: 7
## ── Column specification ─────────────────────────────────────────────────────────────
## Delimiter: ";"
## dbl (7): district_id, car_density, ecar_share, publictransport_meandist, populati...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Join data and transform
german_districts_enhanced <- 
  german_districts %>% 
  dplyr::left_join(attributes_districts, by = "district_id") 

# Check
sf::st_crs(german_districts_enhanced)
## Coordinate Reference System:
##   User input: EPSG:3035 
##   wkt:
## PROJCRS["ETRS89-extended / LAEA Europe",
##     BASEGEOGCRS["ETRS89",
##         ENSEMBLE["European Terrestrial Reference System 1989 ensemble",
##             MEMBER["European Terrestrial Reference Frame 1989"],
##             MEMBER["European Terrestrial Reference Frame 1990"],
##             MEMBER["European Terrestrial Reference Frame 1991"],
##             MEMBER["European Terrestrial Reference Frame 1992"],
##             MEMBER["European Terrestrial Reference Frame 1993"],
##             MEMBER["European Terrestrial Reference Frame 1994"],
##             MEMBER["European Terrestrial Reference Frame 1996"],
##             MEMBER["European Terrestrial Reference Frame 1997"],
##             MEMBER["European Terrestrial Reference Frame 2000"],
##             MEMBER["European Terrestrial Reference Frame 2005"],
##             MEMBER["European Terrestrial Reference Frame 2014"],
##             ELLIPSOID["GRS 1980",6378137,298.257222101,
##                 LENGTHUNIT["metre",1]],
##             ENSEMBLEACCURACY[0.1]],
##         PRIMEM["Greenwich",0,
##             ANGLEUNIT["degree",0.0174532925199433]],
##         ID["EPSG",4258]],
##     CONVERSION["Europe Equal Area 2001",
##         METHOD["Lambert Azimuthal Equal Area",
##             ID["EPSG",9820]],
##         PARAMETER["Latitude of natural origin",52,
##             ANGLEUNIT["degree",0.0174532925199433],
##             ID["EPSG",8801]],
##         PARAMETER["Longitude of natural origin",10,
##             ANGLEUNIT["degree",0.0174532925199433],
##             ID["EPSG",8802]],
##         PARAMETER["False easting",4321000,
##             LENGTHUNIT["metre",1],
##             ID["EPSG",8806]],
##         PARAMETER["False northing",3210000,
##             LENGTHUNIT["metre",1],
##             ID["EPSG",8807]]],
##     CS[Cartesian,2],
##         AXIS["northing (Y)",north,
##             ORDER[1],
##             LENGTHUNIT["metre",1]],
##         AXIS["easting (X)",east,
##             ORDER[2],
##             LENGTHUNIT["metre",1]],
##     USAGE[
##         SCOPE["Statistical analysis."],
##         AREA["Europe - European Union (EU) countries and candidates. Europe - onshore and offshore: Albania; Andorra; Austria; Belgium; Bosnia and Herzegovina; Bulgaria; Croatia; Cyprus; Czechia; Denmark; Estonia; Faroe Islands; Finland; France; Germany; Gibraltar; Greece; Hungary; Iceland; Ireland; Italy; Kosovo; Latvia; Liechtenstein; Lithuania; Luxembourg; Malta; Monaco; Montenegro; Netherlands; North Macedonia; Norway including Svalbard and Jan Mayen; Poland; Portugal including Madeira and Azores; Romania; San Marino; Serbia; Slovakia; Slovenia; Spain including Canary Islands; Sweden; Switzerland; Türkiye (Turkey); United Kingdom (UK) including Channel Islands and Isle of Man; Vatican City State."],
##         BBOX[24.6,-35.58,84.73,44.83]],
##     ID["EPSG",3035]]
head(german_districts_enhanced, 2)
## Simple feature collection with 2 features and 8 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: 4279627 ymin: 3460480 xmax: 4335232 ymax: 3524426
## Projected CRS: ETRS89-extended / LAEA Europe
## # A tibble: 2 × 9
##   district_id GEN                                     geometry car_density ecar_share
##         <dbl> <chr>                         <MULTIPOLYGON [m]>       <dbl>      <dbl>
## 1        1001 Flensburg (((4283235 3524256, 4283267 3524100, …        492.        2.4
## 2        1002 Kiel      (((4331981 3480575, 4332008 3480496, …        453.        2.2
## # ℹ 4 more variables: publictransport_meandist <dbl>, population <dbl>,
## #   green_voteshare <dbl>, afd_voteshare <dbl>

2

We want a first descriptive visual of the distribution of charging stations in Cologne (or any other district of your choice) and the surrounding districts. Filter the district of Cologne (district_id == "05315") and find the surrounding districts. Calculate the number of chargers per district (charger_count) and the number of chargers per 1,000 inhabitants in each district (charger_dens). Plot the two columns for Cologne and its surrounding districts.
You can use the dplyr function sf::bind_rows() to combine the two spatial objects, “Cologne” and “Cologne Surroundings”.
# filter Cologne
cologne <-
  german_districts %>% 
  dplyr::filter(district_id == 5315)

# filter surrounding districts, append with Cologne data and select the charger column
cologne_sur <-
  german_districts %>%
  dplyr::filter(lengths(sf::st_touches(., cologne)) > 0) %>% 
  dplyr::bind_rows(cologne) 


# one pipe to rule them all
cologne_sur_enhanced  <-
  readr::read_delim("./data/charging_points_ger.csv", 
                                  delim =";") %>% 
   filter(!is.na(longitude) & !is.na(latitude)) %>% 
  sf::st_as_sf(
    .,    
    coords = c("longitude", "latitude"),
    crs = 4326
  ) %>% 
  sf::st_transform(. , crs = 3035) %>% 
  sf::st_join(., cologne_sur, join = sf::st_within) %>% 
  dplyr::group_by(district_id) %>%
  dplyr::summarise(charger_count = n()) %>% 
  sf::st_drop_geometry() %>% 
  left_join(cologne_sur, ., by = "district_id") %>% 
  left_join(., attributes_districts %>% dplyr::select(district_id, population), by = "district_id") %>% 
  dplyr::mutate(charger_dens = (charger_count*1000) / population)
## Rows: 60560 Columns: 7
## ── Column specification ─────────────────────────────────────────────────────────────
## Delimiter: ";"
## chr (3): operator, federal_state, type
## dbl (4): latitude, longitude, power_kw, num_plugs
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# plot  
cologne_sur_enhanced %>% 
  dplyr::select(charger_count, charger_dens) %>% 
  plot(.)

3

Save your data set of Cologne and its surrounding districts as an ESRI Shapefile.
# Export as shapefile
sf::st_write(
  cologne_sur_enhanced, 
  dsn = "./data/participant_materials/cologne_charger_epsg3035.shp", 
  delete_layer = TRUE
)