---
title: ""

format: 
  html:
    fig-width: 9
    fig-height: 12
    fig-dpi: 300
    # embed-resources: TRUE # Entwicklung
    # theme: "null" # Entwicklung
    embed-resources: FALSE # Veröffentlichung
    theme: none # Veröffentlichung

execute: 
  echo: FALSE
  output: asis
  warning: FALSE
  error: FALSE
---

```{r}
#| label: pakete_und_daten
#| output: false

library(tidyverse)
library(SMChelpR)
library(DT)
library(scales)

# plotting
library(ggVennDiagram)
library(plotly)
library(colorspace)

library(htmltools)
library(leaflet) # https://rstudio.github.io/leaflet/
library(htmlwidgets)
library(sf)
library(leaflet.extras)
library(rmapshaper)
library(mapview)
library(webshot)

## wichtige Story-Parameter
storyNo <- 24161
file_name_code <- "2024_Stroke_Units.qmd" ########################################
caption_GBA <-
  "Quelle: Qualitätsberichte der Krankenhäuser (G-BA, 2022),\nBerechnungen: Science Media Center Germany."

caption_GBA_DSG <- "Quelle: Qualitätsberichte der Krankenhäuser (G-BA, 2022), DSG,\nBerechnungen: Science Media Center Germany."

caption_Karten <-
  "Quelle: Qualitätsberichte der Krankenhäuser (G-BA, 2022), DSG, BKG,\nBerechnungen: Science Media Center Germany und Uni Wuppertal/Tim Holthaus"

Datumsprefix_files <- FALSE # FALSE, wenn keine regelmäßige Aussendung / keine tagesaktuellen Daten

##############################

imagepath <-
  file.path("reports", storyNo)
dir.create(imagepath, showWarnings = FALSE, recursive = TRUE)

## workspace directory in RStudio interaktiv
if(rstudioapi::isAvailable()) {
  setwd(dirname(rstudioapi::getActiveDocumentContext()$path))
}

if(is.na(file_name_code)){stop("Dateiname der qmd nicht gesetzt")}
if(!file.exists(file_name_code)){stop("qmd existiert nicht. Dateiname falsch?")}

file.copy(
  from = file_name_code, 
  to = file.path(imagepath, paste0(today()[Datumsprefix_files], "_"[Datumsprefix_files], file_name_code)), 
  overwrite = TRUE)
```


```{r}
#| label: set-graphic-parameters
#| output: false 

options(scipen = 999) # set scientific notation to be off
SMC_theme_ggplot()

if (exists("caption_")) {
  stop("Caption wurde nicht angepasst")
}
```


```{r}
#| label: load-data
#| output: false 


data_url <- paste0("https://media.sciencemediacenter.de/reports/", storyNo, "/data")

stroke_units_data <- read_csv(file.path(data_url, "stroke_units_data.csv")) 

load(url(file.path(data_url, "unsere_definition.RData")))
load(url(file.path(data_url, "istzustand.RData")))
load(url(file.path(data_url, "thrombektomie.RData")))
load(url(file.path(data_url, "InEK_Krankenhausliste.RData")))

```

```{r}
#| output: false
unsere_definition |>
  mutate(ueber30 = sek_Klinik_1 > 30*60) |>
  summarise(
    n = sum(ew),
    ueber30 = sum(ew[ueber30]),
    ueber30_prozent = ueber30 / sum(ew) * 100, 
    durchschnitt_fahrzeit = sum(sek_Klinik_1 * ew) / sum(ew) / 60
  )

istzustand |>
  mutate(ueber30 = sek_Klinik_1 > 30*60) |>
  summarise(
    n = sum(ew),
    ueber30 = sum(ew[ueber30]),
    ueber30_prozent = ueber30 / sum(ew) * 100, 
    durchschnitt_fahrzeit = sum(sek_Klinik_1 * ew) / sum(ew) / 60
  )

thrombektomie |>
  mutate(ueber45 = sek_Klinik_1 > 45*60) |>
  summarise(
    n = sum(ew),
    ueber45 = sum(ew[ueber45]),
    ueber45_prozent = ueber45 / sum(ew) * 100, 
    durchschnitt_fahrzeit = sum(sek_Klinik_1 * ew) / sum(ew) / 60
  )


Salzwedel_kliniken <- 
  unsere_definition |> 
  filter(ags == 15081455) |> 
  count(kh_id_Klinik_1)
	
stroke_units_data |>
  filter(Standortnummer %in% as.integer(Salzwedel_kliniken$kh_id_Klinik_1))

thrombektomie |> select(kh_id_Klinik_1) |> distinct()

```
```{r}
#| output: false

# Anfrage Rhein-Zeitung - Rheinland-Pfalz

# - 01 Schleswig-Holstein (SH)
# - 02 Hamburg (HH)
# - 03 Niedersachsen (NI)
# - 04 Bremen (HB)
# - 05 Nordrhein-Westfalen (NW)
# - 06 Hessen (HE)
# - 07 Rheinland-Pfalz (RP)
# - 08 Baden-Württemberg (BW)
# - 09 Bayern (BY)
# - 10 Saarland (SL)
# - 11 Berlin (BE)
# - 12 Brandenburg (BB)
# - 13 Mecklenburg-Vorpommern (MV)
# - 14 Sachsen (SN)
# - 15 Sachsen-Anhalt (ST)
# - 16 Thüringen (TH)

gemeinden_simplified_2019 <- geojsonio::topojson_read(
  file.path(
    "data", 
    "Polygone", 
    "gemeinden_simplified_2019.topojson"
    )
  )

ags_liste_rheinland_pfalz <- gemeinden_simplified_2019 |> 
  filter(SN_L == "07") |> 
  pull(AGS)

# unsere_definition_rheinland_pfalz <-
unsere_definition |> 
  filter(ags %in% ags_liste_rheinland_pfalz) |>
  mutate(ueber30 = sek_Klinik_1 > 30*60,
         ueber60 = sek_Klinik_1 > 60*60) |>
  summarise(
    n = sum(ew),
    ueber30 = sum(ew[ueber30]),
    ueber30_prozent = ueber30 / sum(ew) * 100, 
    ueber60 = sum(ew[ueber60]),
    ueber60_prozent = ueber60 / sum(ew) * 100, 
    durchschnitt_fahrzeit = sum(sek_Klinik_1 * ew) / sum(ew) / 60
  )

# istzustand_rheinland_pfalz <- 
istzustand |> 
  filter(ags %in% ags_liste_rheinland_pfalz) |>
  mutate(ueber30 = sek_Klinik_1 > 30*60,
         ueber60 = sek_Klinik_1 > 60*60) |>
  summarise(
    n = sum(ew),
    ueber30 = sum(ew[ueber30]),
    ueber30_prozent = ueber30 / sum(ew) * 100, 
    ueber60 = sum(ew[ueber60]),
    ueber60_prozent = ueber60 / sum(ew) * 100, 
    durchschnitt_fahrzeit = sum(sek_Klinik_1 * ew) / sum(ew) / 60
  )

thrombektomie |>
  filter(ags %in% ags_liste_rheinland_pfalz) |>
  mutate(ueber45 = sek_Klinik_1 > 45*60) |>
  summarise(
    n = sum(ew),
    ueber45 = sum(ew[ueber45]),
    ueber45_prozent = ueber45 / sum(ew) * 100, 
    durchschnitt_fahrzeit = sum(sek_Klinik_1 * ew) / sum(ew) / 60
  )



```


```{r}
#| label: funktionen-fuer-Kartenvisualisierung
#| output: false 

# könnte ausgelagert werden

create_base_map <- function(base_map_parameters) {
  map <- leaflet(
    options = leafletOptions(
      height = base_map_parameters$height,
      minZoom = base_map_parameters$minZoom,
      maxZoom = base_map_parameters$maxZoom,
      opacity = base_map_parameters$opacity,
      doubleClickZoom = base_map_parameters$doubleClickZoom,
      scrollWheelZoom = base_map_parameters$scrollWheelZoom,
      maxBoundsViscosity = base_map_parameters$maxBoundsViscosity
    )
  ) |>
    setView(
      base_map_parameters$center_lon,
      base_map_parameters$center_lat,
      base_map_parameters$zoom
    ) |>
    setMaxBounds(
      base_map_parameters$min_lon,
      base_map_parameters$min_lat,
      base_map_parameters$max_lon,
      base_map_parameters$max_lat
    ) |>
    htmlwidgets::prependContent(base_map_parameters$extra_style)
  
  return(map)
}

map_add_choropleth_layer <- function(map,
                                     polygon_data,
                                     polygon_color_mapping,
                                     polygon_label,
                                     choropleth_layer_parameters,
                                     leaflet_group) {
  map <- map |>
    addPolygons(
      data = polygon_data,
      fillColor = ~ polygon_color_mapping,
      color = ~ polygon_color_mapping,
      label = polygon_label,
      
      # aesthetic parameters
      smoothFactor = choropleth_layer_parameters$smoothFactor,
      fillOpacity = choropleth_layer_parameters$fillOpacity,
      weight = choropleth_layer_parameters$weight,
      labelOptions = choropleth_layer_parameters$labelOptions,
      highlight = choropleth_layer_parameters$highlight,
      
      # organizational parameters
      group = leaflet_group
    )
  
  return(map)
}

# function, that allows for a diverging color palette with a shifted midpoint
create_custom_palette <- function(low_color,
                                  mid_color,
                                  high_color,
                                  start_point,
                                  mid_point,
                                  end_point) {
  # Create the color function
  f <- function(x) {
    # Rescale values below midpoint
    below_mid <- rescale(x[x <= mid_point],
                         to = c(0, 0.5),
                         from = c(start_point, mid_point))
    
    # Rescale values above midpoint
    above_mid <- rescale(x[x > mid_point],
                         to = c(0.5, 1),
                         from = c(mid_point, end_point))
    
    # Combine the rescaled values
    rescaled <- numeric(length(x))
    rescaled[x <= mid_point] <- below_mid
    rescaled[x > mid_point] <- above_mid
    
    # Create color ramp and apply
    colors <- colorRampPalette(c(low_color, mid_color, high_color))(100)
    color_indices <- round(rescaled * 99) + 1
    return(colors[color_indices])
  }
  
  # Add necessary attributes for leaflet
  attr(f, "colorType") <- "numeric"
  attr(f, "domain") <- c(start_point, end_point)
  attr(f, "range") <- c(low_color, mid_color, high_color)
  attr(f, "interpolate") <- TRUE
  
  return(f)
}


# function, that allows for a diverging color palette with a shifted midpoint
# additionally: exponential scaling of the color ramp
create_custom_palette_exponential <- function(low_color,
                                              mid_color,
                                              high_color,
                                              start_point,
                                              mid_point,
                                              end_point,
                                              exp_factor = 2) {
  f <- function(x) {
    # Rescale values below midpoint with exponentially increasing speed
    below_mid <- x[x <= mid_point]
    if (length(below_mid) > 0) {
      normalized <- (below_mid - start_point) / (mid_point - start_point)
      below_mid <- normalized ^ exp_factor  # exponential scaling
      below_mid <- below_mid * 0.5  # scale to 0-0.5 range
    }
    
    # Rescale values above midpoint with exponentially decreasing speed
    above_mid <- x[x > mid_point]
    if (length(above_mid) > 0) {
      normalized <- (above_mid - mid_point) / (end_point - mid_point)
      above_mid <- 1 - (1 - normalized) ^ exp_factor  # inverse exponential scaling
      above_mid <- 0.5 + (above_mid * 0.5)  # scale to 0.5-1 range
    }
    
    # Combine the rescaled values
    rescaled <- numeric(length(x))
    rescaled[x <= mid_point] <- below_mid
    rescaled[x > mid_point] <- above_mid
    
    # Create color ramp and apply
    colors <- colorRampPalette(c(low_color, mid_color, high_color))(100)
    color_indices <- round(rescaled * 99) + 1
    return(colors[color_indices])
  }
  
  # Add necessary attributes for leaflet
  attr(f, "colorType") <- "numeric"
  attr(f, "domain") <- c(start_point, end_point)
  attr(f, "range") <- c(low_color, mid_color, high_color)
  attr(f, "interpolate") <- TRUE
  
  return(f)
}

addLegendCustom <- function(map, position, colors, labels, sizes, title = NULL, opacity = 0.5){
  colorAdditions <- paste0(colors, "; border-radius: 50%; width:", sizes, "px; height:", sizes, "px")
  labelAdditions <- paste0("<div style='display: inline-block;height: ", 
                           sizes, "px;margin-top: 4px;line-height: ", sizes, "px;'>", 
                           labels, "</div>")

  return(addLegend(map, position, colors = colorAdditions, 
                   labels = labelAdditions, opacity = opacity, title = title
                   ))
}


```


::: m-news-single__ce

- Data Report zur Erreichbarkeit von Kliniken mit und ohne Stroke Unit
- bei einem akuten Schlaganfall beträgt die Fahrzeit zur nächsten Klinik, die Schlaganfälle versorgt, im Durchschnitt 9,5 Minuten
- aber nicht alle dieser Kliniken besitzen eine Stroke Unit, die bessere Behandlungsqualität verspricht
- würden bei einem akuten Schlaganfall ausschließlich Stroke Units angefahren, würde sich die Fahrzeit im Durchschnitt um rund 4,5 Minuten verlängern
- gut 94 Prozent der Bevölkerung würde trotz Konzentration der Versorgung weniger als die empfohlenen 30 Minuten zur nächsten Stroke Unit benötigen und könnten von einer besseren Versorgungsqualität profitieren
- fast 5 Millionen Menschen wären dann insgesamt von einer Fahrzeit über 30 Minuten betroffen, in diesen Regionen braucht es spezielle Versorgungskonzepte
- die durchschnittliche Fahrzeit zu einer Stroke Unit, die auch Thrombektomien durchführen kann, beträgt 18 Minuten

### Einleitung 

Zeit und Qualität sind bei der Behandlung eines Schlaganfalls entscheidend: Wenn die Blutversorgung des Gehirns nicht sichergestellt ist, sterben Nervenzellen ab. Es gilt, den Schlaganfall schnell zu erkennen und leitliniengerecht zu behandeln, um die Schäden im Gehirn möglichst klein zu halten.  

Maximal eine Stunde darf laut des [Eckpunktepapiers 2016 zur notfallmedizinischen Versorgung der Bevölkerung](https://link.springer.com/article/10.1007/s10049-016-0187-0){target="_blank"} nach Eingang des Notrufs vergehen, bis Patient:innen mit potenziellem Schlaganfall das Krankenhaus erreicht haben sollten. Die reine Fahrt bis zum Krankenhaus sollte dabei [nicht mehr als 30 Minuten](https://dserver.bundestag.de/btd/20/134/2013407.pdf){target="_blank"} dauern. 

Aber nicht nur die Zeit allein ist wichtig für die Prognose, sondern vor allem auch die Qualität der Behandlung. Erfolgt diese auf einer sogenannten Stroke Unit (SU), sinkt das Sterberisiko im Vergleich zu einer Klinik ohne Stroke Unit [nachweislich](https://www.sciencedirect.com/science/article/abs/pii/S1052305723002641){target="_blank"}. Ebenso ist das Funktionsniveau im Alltag nach dem Schlaganfall bei Behandlung auf einer Stroke Unit besser. Nicht ohne Grund empfiehlt die [aktuelle medizinische Leitlinie zur Akuttherapie des ischämischen Schlaganfalls](https://dgn.org/leitlinie/akuttherapie-des-ischamischen-schlaganfalls){target="_blank"}, dass alle Schlaganfälle auf einer Stroke Unit behandelt werden sollen.

Die Realität ist eine andere: Eine [Umfrage unter Rettungsdiensten](https://www.springermedizin.de/zerebrale-ischaemie/stroke-unit/praxis-der-praeklinischen-schlaganfallversorgung-im-deutschsprac/23939896){target="_blank"} im deutschsprachigen Raum im Jahr 2020 zeigte, dass bis zu einem Drittel der Patient:innen mit leichter Symptomatik und bis zu 20 Prozent der schwer betroffenen Patient:innen in die nächstgelegene Klinik und damit nicht zwingend in eine zertifizierte Stroke Unit transportiert wurden.

Das SMC hat anhand der [Qualitätsberichte der Krankenhäuser](https://qb-referenzdatenbank.g-ba.de/#/suche){target="_blank"}  aus dem Jahr 2022 ermittelt, an welchen Klinikstandorten Schlaganfälle behandelt wurden, wie lange die Menschen bis zur nächsten Klinik mit oder ohne Stroke Unit fahren müssen und wie sich die Fahrzeiten verändern würden, wenn alle Schlaganfälle ausschließlich zu Klinikstandorten mit Stroke Units gefahren werden würden. Die Fahrzeiten werden für jede Gemeinde auf interaktiven Karten dargestellt. 

Wenn man die Versorgung ausschließlich auf Stroke Units konzentrieren würde, blieben die Fahrzeiten für gut 94 Prozent der Bevölkerung noch immer im Rahmen von 30 Minuten. Der überwiegende Teil der Schlaganfälle könnte dann also fachgerecht und qualitativ in Kliniken mit Stroke Unit behandelt werden, ohne dass sich die Fahrzeit relevant verlängerte. Für die restlichen knapp sechs Prozent der Bevölkerung, die über 30 Minuten fahren würden, müssten spezielle Versorgungskonzepte wie etwa die Luftrettung oder telemedizinische Netzwerke greifen.

Außerdem zeigt der Data Report, an welchen Stroke Units die Möglichkeit zur Thrombektomie besteht, einer Behandlungsmöglichkeit, die das Funktionsniveau von geeigneten Patient:innen nach dem Schlaganfall erheblich verbessern kann.

Diesen Freitag entscheidet der Bundesrat über die [Klinikreform](https://www.bundesrat.de/SharedDocs/drucksachen/2024/0501-0600/532-24.pdf?__blob=publicationFile&v=1){target="_blank"}, in deren Rahmen es auf [Empfehlung der Regierungskommission](https://www.bundesgesundheitsministerium.de/fileadmin/Dateien/3_Downloads/K/Krankenhausreform/5_Stellungnahme_Potenzialanalyse_bf_Version_1.1.pdf){target="_blank"} für eine moderne und bedarfsgerechte Krankenhausversorgung eine Konzentration der Schlaganfall-Akutversorgung auf eine Leistungsgruppe „Stroke Unit“ geben soll – ein Szenario, was die Leitlinie empfiehlt und was in diesem Datenreport dargestellt wird.


```{r}
#| label: stroke-unit-zahlen
#| output: false 

n_stroke_units_unsere_definition <- stroke_units_data |>
  filter(VN24 == TRUE |
           triangulation_max == TRUE | DSG_Zertifiziert == TRUE) |>
  select(Standortnummer) |>
  distinct() |>
  count() |>
  pull()

n_stroke_units_dsg <- stroke_units_data |>
  filter(DSG_Zertifiziert == TRUE) |>
  select(Standortnummer) |>
  distinct() |>
  count() |>
  pull()

n_stroke_units_nicht_zertifiziert <- stroke_units_data |>
  filter(VN24 == TRUE | triangulation_max == TRUE) |>
  filter(is.na(DSG_Zertifiziert)) |>
  distinct() |>
  count() |>
  pull()
```

### Stroke Units in Deutschland 

  
#### Was ist eine Stroke Unit? 

 
Eine [Stroke Unit](https://www.schlaganfall-hilfe.de/de/fuer-betroffene/akutbehandlung/stroke-unit#:~:text=In%20den%20Stroke%20Units%2C%20Spezialeinheiten,so%20viel%20wie%20%E2%80%9EEinheit%22){target="_blank"} ist eine interdisziplinäre Abteilung, die auf Schlaganfälle spezialisiert ist und bestimmte Strukturvoraussetzungen erfüllt.  

Der Begriff Stroke Unit ist allerdings nicht einheitlich definiert: 

So sind [`r format(n_stroke_units_dsg, big.mark=" ", decimal.mark=",")`](https://www.dsg-info.de/stroke-units-neurovaskulaere-netzwerke/){target="_blank"} Stroke Units von der Deutschen Schlaganfall Gesellschaft (DSG, Stand 20.09.2024) [nach festgelegten Kriterien zertifiziert](https://www.dsg-info.de/wp-content/uploads/2022/05/Artikel-DGNeurologie-Zertifizierungskriterien-10.1007_s42451-021-00379-7.pdf){target="_blank"}. Doch nicht alle Stroke Units sind von der DSG zertifiziert oder die jeweiligen Kliniken streben dies gar nicht an.  


In [Studien zur Schlaganfall-Versorgung](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC8948340/){target="_blank"} zählen noch weitere Kliniken als Stroke Unit. Das sind zum Beispiel Kliniken, die in ihren Qualitätsberichten angeben, eine Stroke Unit zu führen und Schlaganfall-Komplexbehandlungen codieren – auch hierfür sind bestimmte [Strukturmerkmale](https://www.icd-code.de/ops/code/8-981.html){target="_blank"} notwendig. Wenn diese Kliniken eine hohe Mindestzahl an Schlaganfällen und Komplexbehandlungen erreichen – und hierdurch Erfahrung bezeugen können – zählen sie auch als Stroke Unit.  

Unsere genaue Definition einer Stroke Unit ist im [Methodenteil](#sec-methoden-definition-stroke-unit) erläutert. Nach unserer Definition und Analyse gibt es in Deutschland  `r format(n_stroke_units_unsere_definition, big.mark=" ", decimal.mark=",")` Stroke Units. Demnach besitzen zusätzlich zu den zertifizierten Kliniken `r format(n_stroke_units_nicht_zertifiziert, big.mark=" ", decimal.mark=",")` Klinikstandorte eine nicht-zertifizierte Stroke Unit.   

#### Fahrzeitberechnung zu Stroke Units 

Auf der folgenden interaktiven Karte sind alle Klinikstandorte mit Stroke Unit markiert. Zudem haben wir die durchschnittliche Fahrzeit zum jeweils nächstgelegenen Klinikstandort mit Stroke Unit für jede Gemeinde visualisiert, sowie die Anzahl der jeweils betroffenen Einwohner:innen von einer Fahrzeit über 30 Minuten. Über das Suchfeld oben rechts kann man einzelne Gemeinden finden.
Die Karte zeigt das Szenario, in dem alle Schlaganfälle ausschließlich an Klinikstandorten mit Stroke Units behandelt werden würden – so wie es Bundesgesundheitsminister Karl Lauterbach mit der [Klinikreform](https://www.bundesrat.de/SharedDocs/drucksachen/2024/0501-0600/532-24.pdf?__blob=publicationFile&v=1){target="_blank"} anstrebt und wie es die [medizinische Leitlinie](https://dgn.org/leitlinie/akuttherapie-des-ischamischen-schlaganfalls){target="_blank"} empfiehlt. 


```{r}
#| label: fahrzeiten-unsere_definition-Daten-laden-und-Parameter-setzen
#| output: false

# plotting the map
base_map_parameters <- list(
  height = 5000,
  minZoom = 4,
  maxZoom = 14,
  opacity = 0,
  center_lon = 9.5,
  center_lat = 51.2,
  zoom = 5.5,
  min_lon = 3,
  min_lat = 47,
  max_lon = 17,
  max_lat = 56,
  doubleClickZoom = FALSE,
  scrollWheelZoom = FALSE,
  maxBoundsViscosity = 0.5,
  # If maxBounds is set, this option controls how solid the bounds are when dragging
  extra_style = tags$style(".leaflet-container { background: white !important; }")
)

choropleth_layer_parameters <- list(
  smoothFactor = 0.2,
  fillOpacity = 1,
  weight = 0,
  labelOptions = labelOptions(style = list(
    "background" = "#f4efe1", # "#cde4f1", # "#e1eff6", # "#B9D9EB",
    "font-size" = "12px"
  )),
  highlight = highlightOptions(
    # on mouseover
    weight = 3,
    color = "black",
    bringToFront = TRUE,
    # sendToBack = TRUE
  )
)

circle_marker_parameters <- list(
  radius = 5,
  stroke = TRUE,
  weight = 0.5,
  fillOpacity = 1,
  labelOptions = labelOptions(style = list("font-size" = "12px")),
  options = markerOptions(riseOnHover = TRUE, pane = "basemap")
)

gemeinden_simplified_2019 <- geojsonio::topojson_read(
  file.path(
    "data", 
    "Polygone", 
    "gemeinden_simplified_2019.topojson"
    )
  )

```


```{r}
#| label: fahrzeiten-unsere_definition-Datenvorverarbeitung
#| output: false

data_to_plot <- unsere_definition

# durchschnittliche (Einwohner-gewichtete) Fahrzeit pro Gemeinde
polygon_data <- data_to_plot |>
  mutate(fahrzeit_in_min = sek_Klinik_1 / 60) |>
  group_by(ags) |>
  summarise(
    weighted_avg_fahrzeit = sum(fahrzeit_in_min * ew, na.rm = TRUE) / sum(ew, na.rm = TRUE),
    total_ew = sum(ew, na.rm = TRUE),
    Anzahl_Betroffene = sum(ew[fahrzeit_in_min > 30], na.rm = TRUE),
    Prozent_Betroffene = sum(ew[fahrzeit_in_min > 30], na.rm = TRUE) / sum(ew, na.rm = TRUE) * 100
  ) |>
  inner_join(gemeinden_simplified_2019, by = c("ags" = "AGS")) |>
  ungroup() |>
  sf::st_as_sf() # ensure that object is a simple-features (sf) object

processed_polygon_data <- polygon_data |>
  mutate(
    pretty_variable_col = format(round(polygon_data[["weighted_avg_fahrzeit"]],1), big.mark =
                                   " ", decimal.mark = ","),
    pretty_variable_col_total_ew = format(polygon_data[["total_ew"]], big.mark =
                                            " ", decimal.mark = ","),
    pretty_variable_col_betroffene_ew = format(polygon_data[["Anzahl_Betroffene"]], big.mark =
                                                 " ", decimal.mark = ","),
    pretty_variable_col_prozent_betroffene = format(
      round(polygon_data[["Prozent_Betroffene"]], 2),
      big.mark = " ",
      decimal.mark = ","
    )
  ) |>
  mutate(
    label = paste0(
      "<strong>",
      GEN,
      "</strong>",
      "<br/>Fahrzeit in min: ",
      pretty_variable_col,
      "<br/>Einwohner:innen: ",
      pretty_variable_col_total_ew,
      "<br/>Betroffene Einwohner:innen: ",
      pretty_variable_col_betroffene_ew,
      "<br/>Prozent Betroffene: ",
      pretty_variable_col_prozent_betroffene,
      "%"
    )
  ) |>
  rowwise() |> # transform rowwise to html tag
  mutate(label = HTML(label))

```

```{r}
#| label: fahrzeiten-unsere_definition-Colormap
#| output: false

my_palette <- create_custom_palette_exponential(
  low_color <- "#91cf60",
  mid_color <- "#ffffbf",
  high_color <- "#a50026",
  start_point = 0,
  mid_point = 30,
  end_point = max(processed_polygon_data$weighted_avg_fahrzeit),
  exp_factor = 2  # adjust this to control the transition speed
  
)


# Create binned version using colorBin

## Create sequence of values across our range
sample_values <- c(0, 20, 25, 45, 60, 80, 120)

## Get colors for these values using our custom palette
colors <- my_palette(sample_values)

## create a function that maps numeric value to color
binned_palette <- colorBin(
  palette = colors,
  domain = c(0, max(
    processed_polygon_data$weighted_avg_fahrzeit
  )),
  bins = c(0, 10, 20, 30, 40, 50, 60, Inf),
  na.color = "transparent"
)

polygon_color_mapping <- binned_palette(processed_polygon_data$weighted_avg_fahrzeit)

# for future use in Istzustand-Karte
processed_polygon_data_nur_SU <- processed_polygon_data
polygon_color_mapping_nur_SU <- polygon_color_mapping
binned_palette_nur_SU <- binned_palette

choropleth_legend_colors <- colors
choropleth_legend_labels = c("0-10", "10-20", "20-30", "30-40", "40-50", "50-60", ">60")


marker_colors = c(
  "überregionale Stroke Unit" = "#589296",
  "alle anderen Stroke Units" = "#8bc5c9",
  "Tele-Stroke-Unit" = "#bffbff",
  "keine Stroke Unit" = "#d3d3d3"
  )

```

```{r}
#| label: fahrzeiten-unsere_definition-Tooltip
#| output: false


data_info <- stroke_units_data |>
  filter(VN24 == TRUE |
           triangulation_max == TRUE | DSG_Zertifiziert == TRUE) |>
  mutate(
    label = paste0(
      "<strong>",
      ifelse(is.na(Name), Einrichtung_Name, Name),
      # per default "Name" der DSG-Liste, sonst "Einrichtung_Name" der InEK-Liste
      "</strong>",
      "<br/>",
      "<p>Ort / PLZ: ",
      ifelse(is.na(Ort), Einrichtung_GeoAdresse_Ort, Ort),
      " / ",
      ifelse(
        is.na(Postleitzahl),
        Einrichtung_GeoAdresse_PLZ,
        Postleitzahl
      ),
      "<br/>",
      "<p>Fallzahl ICD: ",
      Fallzahl_ICD_Schlaganfall_max,
      "<br/>",
      "Fallzahl OPS: ",
      Fallzahl_OPS_Schlaganfall_max,
    '<br/></p>',
    "<p>Neurologie: ",
    neurologie_label,
    '</p>',      # "8-981.2: ",
      # Fallzahl_OPS_regionale_SU_max,
      # "<br/>",
      # "8-981.3: ",
      # Fallzahl_OPS_ueberregionale_SU_max,
      # "<br/>",
      # "8-98b.2: ",
      # Fallzahl_OPS_andere_SU_ohne_Telekonsildienst_max,
      # "<br/>",
      # "8-98b.3: ",
      # Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max,
      # '<br/></p>',
      "VN24: ",
      VN24_label,
      "<br/>",
      "ICD/OPS-Kriterium: ",
      icd_ops_kriterium_label,
      '<br/>',
      "Zertifiziert als: ",
      Zertifiziert_als_label
    )
  ) |>
  rowwise() |> # transform rowwise to html tag
  mutate(label = HTML(label))

data_info <- data_info |>
  mutate(
    group = case_when(
      Zertifiziert_als %in% c("Überregionale Stroke Unit", "Überregionale Comprehensive Stroke Unit") ~ "überregionale Stroke Unit",
      (Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > 0  &
        Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > coalesce(Fallzahl_OPS_regionale_SU_max, 0) &
        Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > coalesce(Fallzahl_OPS_ueberregionale_SU_max, 0) &
        Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > coalesce(Fallzahl_OPS_andere_SU_ohne_Telekonsildienst_max, 0)) ~ "Tele-Stroke-Unit",
      TRUE ~ "alle anderen Stroke Units"
    )
  ) |> 
  mutate(
    fillColor = case_when(
      group == "überregionale Stroke Unit" ~ marker_colors[["überregionale Stroke Unit"]],
      group == "alle anderen Stroke Units" ~ marker_colors[["alle anderen Stroke Units"]],
      group == "Tele-Stroke-Unit" ~ marker_colors[["Tele-Stroke-Unit"]]
    ),
    color = "black",
  )

```


```{r}
#| label: fahrzeiten-unsere_definition-Zusammenbau-der-Karte
#| output: true

map <- create_base_map(base_map_parameters) |>
  addMapPane("choropleth", zIndex = 400) |>
  map_add_choropleth_layer(
    polygon_data = processed_polygon_data,
    polygon_color_mapping = polygon_color_mapping,
    polygon_label = processed_polygon_data$label,
    choropleth_layer_parameters = choropleth_layer_parameters,
    leaflet_group = "Fahrzeiten"
  ) |>
  addMapPane("basemap", zIndex = 500) |>
  addTiles(urlTemplate = "https://tileserver.smc.report/data/all_zoom_levels/{z}/{x}/{y}.png",
         options = pathOptions(pane = "basemap"),
         group = "basemap") |>
  addMapPane("clinics", zIndex = 600) |>
  addCircleMarkers(
    data = data_info,
    label = data_info$label,
    fillColor = data_info$fillColor,
    color = data_info$color,
    radius = circle_marker_parameters$radius,
    stroke = circle_marker_parameters$stroke,
    weight = circle_marker_parameters$weight,
    fillOpacity = circle_marker_parameters$fillOpacity,
    labelOptions = circle_marker_parameters$labelOptions,
    options = circle_marker_parameters$options,
    group = data_info$group
  ) |>
  addLegend(
    # choropleth
    "bottomleft",
    # pal = binned_palette,
    values = processed_polygon_data$weighted_avg_fahrzeit,
    title = HTML("Fahrzeit in min"),
    opacity = 1,
    colors = choropleth_legend_colors,
    labels = choropleth_legend_labels
  ) |>
  addLegendCustom(
    # markers
    "bottomright",
    colors = c(marker_colors["überregionale Stroke Unit"], marker_colors["alle anderen Stroke Units"], marker_colors["Tele-Stroke-Unit"]),
    labels = c("überregionale Stroke Unit", "alle anderen Stroke Units", "Tele-Stroke-Unit"),
    sizes = 15,
    title = HTML("Stroke Units"),
    opacity = 1
  ) |>
  addResetMapButton() |>
  addSearchFeatures(
    targetGroups  = c("Fahrzeiten", unique(unname(data_info$group))),
    options = searchFeaturesOptions(
      zoom = 10,
      openPopup = FALSE,
      autoCollapse = TRUE,
      position = "topright",
      marker = list(
        icon = NULL,
        animate = TRUE,
        circle = list(
          radius = 10,
          weight = 3,
          color = "orange",
          stroke = TRUE,
          fill = FALSE
        )
      )
    )
  ) |>
  leaflet.extras::addFullscreenControl(position = "topleft") |> 
  addGroupedLayersControl(
    # baseGroups = c("basemap"),
    overlayGroups = list("Stroke Units" = c("überregionale Stroke Unit", "alle anderen Stroke Units", "Tele-Stroke-Unit")),
    position = c("bottomright"),
    options = groupedLayersControlOptions(
      groupCheckboxes = FALSE,
      collapsed = FALSE,
      groupsCollapsable = FALSE,
      sortLayers = FALSE,
      sortGroups = FALSE,
      sortBaseLayers = FALSE,
      exclusiveGroups = character(0)
    )
  )

map

filename <- "Fahrzeiten_Stroke_Units"

data_choropleth <- tibble(
  fileformat = c("csv", "csv"),
  filename_suffix = c("Kliniken", "Fahrtzeiten")
)
images_choropleth <- tibble(
  fileformat = c("html"),
  filename_suffix = c("")
)

htmlpfad <- file.path(imagepath, paste0(filename, ".html"))
datenpfad_clinics <- file.path(imagepath, paste0(filename, "_Kliniken.csv"))
datenpfad_distance <- file.path(imagepath, paste0(filename, "_Fahrtzeiten.csv"))

mapshot(map, url=htmlpfad)

processed_polygon_data |>
  select(
    ags,
    weighted_avg_fahrzeit,
    total_ew,
    Anzahl_Betroffene,
    Prozent_Betroffene,
    BEZ,
    GEN,
    NUTS,
    BEM,
    OBJECTID,
    EWZ,
    KFL,
    pretty_variable_col,
    pretty_variable_col_total_ew,
    pretty_variable_col_betroffene_ew,
    pretty_variable_col_prozent_betroffene,
    label
  ) |> 
  as_tibble() |> 
  write_csv(datenpfad_distance)

data_info |>
  select(
    Standortnummer, 
    Zertifiziert_als,
    VN24, VN24_label,
    Bezeichnung, 
    ReferenzKrankenhaus_IK,
    StandortId,
    lat,
    lon,
    Einrichtung_GeoAdresse_PLZ,
    Einrichtung_GeoAdresse_Ort,
    Einrichtung_GeoAdresse_Straße,
    Einrichtung_GeoAdresse_Hausnummer,
    Einrichtung_GeoAdresse_AdressZusatz,
    Gemeindeschlüssel,
    neurologie_label,
    label
  ) |>
  as_tibble() |> 
  write_csv(datenpfad_clinics)


image_helper_light(
  filename = filename,
  filepath = imagepath,
  data = data_choropleth,
  images = images_choropleth,
  captions = caption_Karten
)

```

**Überregionale Stroke Units**: [Von der DSG zertifizierte](https://www.dsg-info.de/wp-content/uploads/2022/05/Artikel-DGNeurologie-Zertifizierungskriterien-10.1007_s42451-021-00379-7.pdf){target="_blank"} überregionale Stroke Units sind besonders ausgestattet und bieten spezielle Behandlungsmöglichkeiten, wie die mechanische Thrombektomie, rund um die Uhr an. Hier können auch besonders komplexe Schlaganfälle behandelt werden, weil die Möglichkeiten an Diagnostik und Therapie breiter sind – es gibt etwa rund um die Uhr Neuroradiolog:innen und spezielle Arten der CT. Sie haben ein größeres Einzugsgebiet und übernehmen komplexe Fälle aus den anderen Stroke Units. 

**Tele-Stroke-Units**: Diese Stroke Units versorgen die Mehrzahl ihrer Schlaganfälle mithilfe telemedizinischer Konsile. Das bedeutet, dass sie den neurologischen Sachverstand einer anderen Stroke Unit über einen Telekonsildienst in Anspruch nehmen, wenn zum Beispiel die dort angestellten Neurolog:innen nicht anwesend sind. Dafür codieren sie in ihren jährlichen Qualitätsberichten den [OPS-Code 8-98b.3 (Anwendung eines Telekonsildienstes)](https://www.icd-code.de/ops/code/8-98b.html){target="_blank"}. Dies können auch zertifizierte regionale Stroke Units sein, wenn sie vorwiegend diesen OPS-Code codieren.

**Weitere Stroke Units**: Hierunter fallen zunächst die [zertifizierten](https://www.dsg-info.de/wp-content/uploads/2022/05/Artikel-DGNeurologie-Zertifizierungskriterien-10.1007_s42451-021-00379-7.pdf){target="_blank"} regionalen Stroke Units. Regionale Stroke Units sind für die Versorgung weniger komplexer Schlaganfälle ausgelegt. Auch andere nicht-zertifizierte Stroke Units, die bestimmte Mindestfallzahlen aufweisen oder in ihren Qualitätsberichten angeben, eine Stroke Unit zu haben, sind hierunter zusammengefasst ([siehe Methoden](#sec-methoden-definition-stroke-unit)).

Für jede aufgeführte Stroke Unit finden sich Details zur konkreten Struktur des Klinikstandorts: 

- die ICD-Fallzahl an Schlaganfällen zeigt, wie viele Schlaganfälle vor Ort codiert wurden; ICD-Codes klassifizieren Diagnosen
- die OPS-Fallzahl an neurologischen Komplexbehandlungen zeigt, wie viele Schlaganfall-Komplexbehandlungen hier codiert wurden; OPS-Codes sind ein Abrechnungsinstrument für konkrete medizinische Prozeduren, im Vergleich zu ICD-Codes liegen die Fallzahlen niedriger, da eine Diagnose häufiger dokumentiert wird als eine medizinische Prozedur, die nicht bei allen Patient:innen erfolgt oder codiert werden kann. Die Angabe der OPS-Codes lässt aber auf wichtige Strukturmerkmale schließen
- der „VN24“-Status zeigt, ob der Klinikstandort im Qualitätsbericht angegeben hat, eine Stroke Unit zu haben. Diese Angabe ist unabhängig von der strukturellen Ausstattung, weshalb der Status allein nicht sehr 
aussagekräftig ist ([siehe Venn-Diagramm](#sec-methoden-definition-stroke-unit))
- unser eigenes OPS/ICD-Kriterium zeigt, ob vor Ort eine Mindestzahl an Schlaganfällen (250 ICD-Codes) und Schlaganfall-Komplexbehandlungen (125 OPS-Codes) [codiert wurden](#sec-methoden-definition-stroke-unit), die wir in unsere Definition von Stroke Units miteinbezogen haben
- [der Zertifizierungsstatus nach DSG](https://www.dsg-info.de/wp-content/uploads/2022/05/Artikel-DGNeurologie-Zertifizierungskriterien-10.1007_s42451-021-00379-7.pdf){target="_blank"} zeigt, ob und als was die Stroke Unit von der DSG zertifiziert ist 

Auch für jede Gemeinde geben wir Details an: 

- die durchschnittliche Fahrzeit der Einwohner:innen zum nächsten Klinikstandort mit Stroke Unit 
- die Zahl der Einwohner:innen 
- die Zahl der Einwohner:innen, die von einer Fahrzeit über 30 Minuten betroffen ist („betroffene Einwohner:innen“)
- der Anteil der Einwohner:innen der Gemeinde, der von einer Fahrzeit über 30 Minuten betroffen ist („Prozent Betroffene“)

##### Was zeigt nun eine regionale Analyse der Erreichbarkeit von Stroke Units?

Die durchschnittliche Fahrzeit zu einem Klinikstandort mit Stroke Unit würde in dem vom SMC berechneten Szenario etwa 14 Minuten betragen. Rund 94 Prozent der Bevölkerung würden eine Stroke Unit innerhalb der 30 Minutengrenze erreichen. Knapp 5 Millionen Menschen würden länger als 30 Minuten bis zu einem Klinikstandort mit Stroke Unit benötigen. Das bedeutet, dass für diese knapp sechs Prozent der Gesamtbevölkerung alternative Versorgungsstrukturen realisiert werden müssten. 

In der folgenden interaktiven Tabelle sind bundesweit alle Gemeinden mit einer durchschnittlichen Fahrzeit über 30 Minuten bis zur nächsten SU nach unserem Szenario aufgelistet. Es gibt die Möglichkeit, nach Gemeinden zu suchen, oder die Tabelle nach bestimmten Kriterien zu ordnen: Mit einem Klick auf die entsprechende Spaltenüberschrift kann man zum Beispiel die Spalte „Einwohner:innen“ ordnen. So können Gemeinden gefunden werden, die viele Einwohner:innen haben und von einer Fahrzeit über 30 Minuten betroffen wären. Es gibt auch die Möglichkeit, nur einen selbstdefinierten Bereich anzuzeigen: Zum Beispiel nur Gemeinden in Niedersachsen mit der Eingabe des entsprechenden [Länderkürzels](https://www.datenportal.bmbf.de/portal/de/G122.html){target="_blank"} in der Spalte Bundesland.  

```{r}


bundesland_mapping <- c(
  "01" = "SH",
  "02" = "HH",
  "03" = "NI",
  "04" = "HB",
  "05" = "NW",
  "06" = "HE",
  "07" = "RP",
  "08" = "BW",
  "09" = "BY",
  "10" = "SL",
  "11" = "BE",
  "12" = "BB",
  "13" = "MV",
  "14" = "SN",
  "15" = "ST",
  "16" = "TH"
)


# durchschnittliche (Einwohner-gewichtete) Fahrzeit pro Gemeinde
unsere_definition |>
  mutate(fahrzeit_in_min = sek_Klinik_1 / 60) |>
  group_by(ags) |>
  summarise(
    weighted_avg_fahrzeit = sum(fahrzeit_in_min * ew, na.rm = TRUE) / sum(ew, na.rm = TRUE),
    total_ew = sum(ew, na.rm = TRUE),
    Anzahl_Betroffene = sum(ew[fahrzeit_in_min > 30], na.rm = TRUE),
    Prozent_Betroffene = sum(ew[fahrzeit_in_min > 30], na.rm = TRUE) / sum(ew, na.rm = TRUE) * 100
  ) |>
  inner_join(gemeinden_simplified_2019, by = c("ags" = "AGS")) |>
  ungroup() |>
  filter(weighted_avg_fahrzeit > 30) |>
  mutate(
    Gemeinde = GEN,
    Fahrzeit = round(weighted_avg_fahrzeit, 2),
    `Einwohner:innen` = total_ew,
    `Betroffene Einwohner:innen` = Anzahl_Betroffene,
    `Prozent Betroffene` = round(Prozent_Betroffene, 2),
    Bundesland = bundesland_mapping[SN_L]
    ) |>
  select(Gemeinde, Bundesland, Fahrzeit, `Einwohner:innen`, `Betroffene Einwohner:innen`, `Prozent Betroffene`) |>
  arrange(desc(`Betroffene Einwohner:innen`)) |>
  mutate(
    Fahrzeit = prettyNum(Fahrzeit, big.mark = " ", decimal.mark = ","),
    # `Betroffene Einwohner:innen` = prettyNum(`Betroffene Einwohner:innen`, big.mark = " ", decimal.mark = ","),
    # `Einwohner:innen` = prettyNum(`Einwohner:innen`, big.mark = " ", decimal.mark = ","),
    `Prozent Betroffene` = percent(`Prozent Betroffene`, decimal.mark = ",", scale = 1, accuracy = 1)
    ) |>
  datatable(filter = 'top', options = list(pageLength = 5), rownames = FALSE)

```

```{=html}
<center></center>
```

Eine versorgungsschwächere Region wäre zum Beispiel die Region Altmark im nördlichen Sachsen-Anhalt, wo Patient:innen teils 50 Minuten und länger zum nächsten Stroke-Unit-Klinikstandort fahren müssten. In der dortigen Stadt Salzwedel würden knapp 23<span style=„font-size:50%;“> </span>000 Menschen durchschnittlich 49 Minuten zur nächsten Stroke Unit im niedersächsischen Uelzen fahren. Auch in der Stadt Stendal wären gut 37<span style=„font-size:50%;“> </span>000 Menschen von einer durchschnittlichen Fahrzeit von 44 Minuten betroffen. In Stendal wird jedoch derzeit diese Versorgungslücke geschlossen, indem dort eine [neue Stroke Unit]( https://www.johanniter.de/johanniter-kliniken/stendal/medizin-pflege/neurologie-und-geriatrie/){target="_blank"} aufgebaut wird. Ein ähnliches Beispiel ist das nordrheinwestfälische Bad Berleburg, wo es auch [bald eine Stroke Unit](https://www.wp.de/lokales/wittgenstein/article406709240/krankenhausreform-bad-berleburg-bekommt-eine-stroke-unit.html<){target="_blank"} geben wird.

In Ballungszentren und Städten wie Köln oder Berlin gäbe es hingegen keinerlei Probleme, was die Fahrzeit bis zur nächsten Stroke Unit betrifft: In vielen Fällen bräuchte ein Pkw weniger als zehn Minuten zum Klinikstandort mit Stroke Unit. 

### Aktuelle Schlaganfall-Versorgung 

Das vorherige Szenario entspricht derzeit noch nicht der Realität. In Deutschland wurde im Jahr 2021 nach [Berechnungen für das Bundesgesundheitsministerium](https://www.bundesgesundheitsministerium.de/fileadmin/Dateien/3_Downloads/K/Krankenhausreform/5_Stellungnahme_Potenzialanalyse_bf_Version_1.1.pdf){target="_blank"} jede:r vierte Schlaganfall-Patient:in in einer Klinik versorgt, die keine Stroke Unit hat. Das könnte teilweise daran liegen, dass die nächste Stroke Unit weit entfernt ist oder diese keine Kapazitäten mehr hat, oder aber auch an einer [Fehlverteilung](https://www.springermedizin.de/zerebrale-ischaemie/stroke-unit/praxis-der-praeklinischen-schlaganfallversorgung-im-deutschsprac/23939896){target="_blank"} von Schlaganfall-Patient:innen an Kliniken, die eigentlich gar keine Schlaganfälle behandeln sollten.

#### Fahrzeitberechnung zu Schlaganfall-Versorgern

Auf der folgenden Karte sind alle Klinikstandorte erkennbar, die Schlaganfälle versorgen: Dargestellt sind alle Häuser mit Stroke Units nach unserer Definition und zusätzlich alle anderen Klinikstandorte, die mindestens zehn Schlaganfall-Diagnosen oder mindestens 5 Schlaganfall-Prozeduren in ihren Qualitätsberichten angegeben haben. Damit nähert sich die Karte an ein realistisches Szenario der kompletten derzeitigen Schlaganfall-Versorgung an. Die Fahrzeitenberechnung erfolgt hier nun zu allen Klinikstandorten, die Schlaganfälle versorgen.


```{r}
#| label: fahrzeiten-istzustand-Datenvorverarbeitung
#| output: false

data_to_plot <- istzustand

# durchschnittliche (Einwohner-gewichtete) Fahrzeit pro Gemeinde
polygon_data <- data_to_plot |>
  mutate(fahrzeit_in_min = sek_Klinik_1 / 60) |>
  group_by(ags) |>
  summarise(weighted_avg_fahrzeit = sum(fahrzeit_in_min * ew, na.rm = TRUE) / sum(ew, na.rm = TRUE),
            total_ew = sum(ew, na.rm = TRUE),
            Anzahl_Betroffene = sum(ew[fahrzeit_in_min > 30], na.rm = TRUE),
            Prozent_Betroffene = sum(ew[fahrzeit_in_min > 30], na.rm = TRUE) / sum(ew, na.rm = TRUE) * 100
            ) |>
  inner_join(gemeinden_simplified_2019, by = c("ags" = "AGS")) |>
  ungroup() |>
  sf::st_as_sf() # ensure that object is a simple-features (sf) object

processed_polygon_data <- polygon_data |>
  mutate(
    pretty_variable_col = format(round(polygon_data[["weighted_avg_fahrzeit"]],1), big.mark=" ", decimal.mark=","),
    pretty_variable_col_total_ew = format(polygon_data[["total_ew"]], big.mark=" ", decimal.mark=","),
    pretty_variable_col_betroffene_ew = format(polygon_data[["Anzahl_Betroffene"]], big.mark=" ", decimal.mark=","),
    pretty_variable_col_prozent_betroffene = format(round(polygon_data[["Prozent_Betroffene"]],2), big.mark=" ", decimal.mark=",")
    ) |>
  mutate(
    label = paste0(
      "<strong>", GEN, "</strong>",
      "<br/>Fahrzeit in min: ", pretty_variable_col,
      "<br/>Einwohner:innen: ", pretty_variable_col_total_ew,
      "<br/>Betroffene Einwohner:innen: ", pretty_variable_col_betroffene_ew,
      "<br/>Prozent Betroffene: ", pretty_variable_col_prozent_betroffene, "%"
    )
  ) |>
  rowwise() |> # transform rowwise to html tag
  mutate(
    label = HTML(label)
  )


```

```{r}
#| label: fahrzeiten-istzustand-Colormap
#| output: false

processed_polygon_data_istzustand <- processed_polygon_data
polygon_color_mapping_istzustand <- binned_palette(processed_polygon_data_istzustand$weighted_avg_fahrzeit)

```


```{r}
#| label: fahrzeiten-istzustand-Tooltip
#| output: false


data_info <- stroke_units_data |>
  filter(
    Fallzahl_OPS_Schlaganfall_max > 5 |
      Fallzahl_ICD_Schlaganfall_max > 10 |
      VN24 == TRUE |
      triangulation_max == TRUE | DSG_Zertifiziert == TRUE
  ) |>
  mutate(
    label = paste0(
    "<strong>",
    ifelse(is.na(Name), Einrichtung_Name, Name), # per default "Name" der DSG-Liste, sonst "Einrichtung_Name" der InEK-Liste
    "</strong>",
    "<br/>",
    "<p>Ort / PLZ: ",
    ifelse(is.na(Ort), Einrichtung_GeoAdresse_Ort, Ort), " / ", ifelse(is.na(Postleitzahl), Einrichtung_GeoAdresse_PLZ, Postleitzahl),
    "<br/>",
    "<p>Fallzahl ICD: ",
    Fallzahl_ICD_Schlaganfall_max,
    "<br/>",
    "Fallzahl OPS: ",
    Fallzahl_OPS_Schlaganfall_max,
    "<br/>",
    "Fallzahl Reha-OPS: ",
    Fallzahl_OPS_Reha_max,
    '<br/></p>',
    "<p>Neurologie: ",
    neurologie_label,
    '</p>',
    "VN24: ",
    VN24_label,
    "<br/>",
    "ICD/OPS-Kriterium: ",
    icd_ops_kriterium_label,
    '<br/>',
    "Zertifiziert als: ",
    Zertifiziert_als_label
  )
  ) |>
  rowwise() |> # transform rowwise to html tag
  mutate(
    label = HTML(label)
  )


data_info <- data_info |>
  mutate(
    unsere_definition = case_when(
    (VN24 == TRUE | triangulation_max == TRUE | DSG_Zertifiziert == TRUE) ~ TRUE,
    is.na((VN24 == TRUE | triangulation_max == TRUE | DSG_Zertifiziert == TRUE)) ~ FALSE
    )
  ) |>
  mutate(
    group = case_when(
      Zertifiziert_als %in% c("Überregionale Stroke Unit", "Überregionale Comprehensive Stroke Unit") ~ "überregionale Stroke Unit",
      (Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > 0  &
        Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > coalesce(Fallzahl_OPS_regionale_SU_max, 0) &
        Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > coalesce(Fallzahl_OPS_ueberregionale_SU_max, 0) &
        Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > coalesce(Fallzahl_OPS_andere_SU_ohne_Telekonsildienst_max, 0) &
         unsere_definition == TRUE) ~ "Tele-Stroke-Unit",
      (unsere_definition == FALSE) ~ "keine Stroke Unit",
      TRUE ~ "alle anderen Stroke Units"
    )
  ) |> 
  mutate(
    fillColor = case_when(
      group == "überregionale Stroke Unit" ~ marker_colors[["überregionale Stroke Unit"]],
      group == "alle anderen Stroke Units" ~ marker_colors[["alle anderen Stroke Units"]],
      group == "Tele-Stroke-Unit" ~ marker_colors[["Tele-Stroke-Unit"]],
      group == "keine Stroke Unit" ~ marker_colors[["keine Stroke Unit"]]
    ),
    color = "black",
  ) |>
  mutate(marker_groups = case_when(
    is.na(Fallzahl_ICD_Schlaganfall_max) ~ "kein ICD-Code angegeben",
    Fallzahl_ICD_Schlaganfall_max <= 50 ~ "unter 50 Fälle",
    Fallzahl_ICD_Schlaganfall_max > 50 & Fallzahl_ICD_Schlaganfall_max <= 150 ~ "zwischen 50 und 150 Fälle",
    Fallzahl_ICD_Schlaganfall_max > 150 & Fallzahl_ICD_Schlaganfall_max <= 250 ~ "zwischen 150 und 250 Fälle",
    Fallzahl_ICD_Schlaganfall_max > 250 ~ "über 250 Fälle",
    )
  ) |> 
  mutate(stroke_yes_no = case_when(
    unsere_definition == TRUE ~ "Stroke Units",
    unsere_definition == FALSE ~ "keine Stroke Units"
  ))

ICD_classes = c("über 250 Fälle", "zwischen 150 und 250 Fälle", "zwischen 50 und 150 Fälle", "unter 50 Fälle", "kein ICD-Code angegeben")

```


```{r}
#| label: fahrzeiten-istzustand-Zusammenbau-der-Karte
#| output: true


map <- create_base_map(base_map_parameters) |>
  addMapPane("choropleth", zIndex = 400) |>
  map_add_choropleth_layer(
    polygon_data = processed_polygon_data_istzustand,
    polygon_color_mapping = polygon_color_mapping_istzustand,
    polygon_label = processed_polygon_data_istzustand$label,
    choropleth_layer_parameters = choropleth_layer_parameters,
    leaflet_group = "Fahrzeiten"
  ) |>
  addMapPane("basemap", zIndex = 500) |>
  addTiles(urlTemplate = "https://tileserver.smc.report/data/all_zoom_levels/{z}/{x}/{y}.png",
         options = pathOptions(pane = "basemap")) |>
  addMapPane("clinics", zIndex = 600) |>
  addCircleMarkers(
    data = data_info,
    label = data_info$label,
    fillColor =  data_info$fillColor,
    color = data_info$color,
    radius = circle_marker_parameters$radius,
    stroke = circle_marker_parameters$stroke,
    weight = circle_marker_parameters$weight,
    fillOpacity = circle_marker_parameters$fillOpacity,
    labelOptions = circle_marker_parameters$labelOptions,
    options = circle_marker_parameters$options,
    group = data_info$marker_groups
  ) |>
  addCircleMarkers(
    data = data_info,
    label = data_info$label,
    fillColor =  data_info$fillColor,
    color = data_info$color,
    radius = circle_marker_parameters$radius,
    stroke = circle_marker_parameters$stroke,
    weight = circle_marker_parameters$weight,
    fillOpacity = circle_marker_parameters$fillOpacity,
    labelOptions = circle_marker_parameters$labelOptions,
    options = circle_marker_parameters$options,
    group = data_info$stroke_yes_no
  ) |>
  addLegend(
    # choropleth
    "bottomleft",
    # pal = my_palette,
    # pal = binned_palette,
    colors = choropleth_legend_colors,
    values = processed_polygon_data$weighted_avg_fahrzeit,
    title = HTML("Fahrzeit in min"),
    opacity = 1,
    labels = c("0-10", "10-20", "20-30", "30-40", "40-50", "50-60", ">60")
  ) |>
  addLegendCustom(
    # markers
    "bottomright",
    colors = unname(marker_colors),
    labels = names(marker_colors),
    title = HTML("Schlaganfall-Versorger"),
    sizes = 15,
    opacity = 1
    # group = "markers"
  ) |>
  addResetMapButton() |>
  addSearchFeatures(
    targetGroups  = c("Fahrzeiten", unique(unname(data_info$group))),
    options = searchFeaturesOptions(
      zoom = 10,
      openPopup = FALSE,
      autoCollapse = TRUE,
      position = "topright",
      marker = list(
        icon = NULL,
        animate = TRUE,
        circle = list(
          radius = 10,
          weight = 3,
          color = "orange",
          stroke = TRUE,
          fill = FALSE
        )
      )
    )
  ) |>
  leaflet.extras::addFullscreenControl(position = "topleft")

    map <- addGroupedLayersControl(
      map,
      # baseGroups = c("basemap"),
      overlayGroups = list("Schlaganfall-Versorger" = c("Stroke Units", "keine Stroke Units")),
      position = c("bottomright"),
      options = groupedLayersControlOptions(
        groupCheckboxes = TRUE,
        collapsed = FALSE,
        groupsCollapsable = FALSE,
        sortLayers = FALSE,
        sortGroups = FALSE,
        sortBaseLayers = FALSE,
        exclusiveGroups = character(0)
      )
    ) |> 
      hideGroup(ICD_classes) 

map

filename <- "Fahrzeiten_Istzustand"

data_choropleth <- tibble(
  fileformat = c("csv", "csv"),
  filename_suffix = c("Kliniken", "Fahrtzeiten")
)
images_choropleth <- tibble(
  fileformat = c("html"),
  filename_suffix = c("")
)

htmlpfad <- file.path(imagepath, paste0(filename, ".html"))
datenpfad_clinics <- file.path(imagepath, paste0(filename, "_Kliniken.csv"))
datenpfad_distance <- file.path(imagepath, paste0(filename, "_Fahrtzeiten.csv"))

mapshot(map, url=htmlpfad)

processed_polygon_data |>
  select(
    ags,
    weighted_avg_fahrzeit,
    total_ew,
    Anzahl_Betroffene,
    Prozent_Betroffene,
    BEZ,
    GEN,
    NUTS,
    BEM,
    OBJECTID,
    EWZ,
    KFL,
    pretty_variable_col,
    pretty_variable_col_total_ew,
    pretty_variable_col_betroffene_ew,
    pretty_variable_col_prozent_betroffene,
    label
  ) |> 
  as_tibble() |> 
  write_csv(datenpfad_distance)

data_info |>
  select(
    Standortnummer, 
    Zertifiziert_als,
    VN24, VN24_label,
    Bezeichnung, 
    ReferenzKrankenhaus_IK,
    StandortId,
    lat,
    lon,
    Einrichtung_GeoAdresse_PLZ,
    Einrichtung_GeoAdresse_Ort,
    Einrichtung_GeoAdresse_Straße,
    Einrichtung_GeoAdresse_Hausnummer,
    Einrichtung_GeoAdresse_AdressZusatz,
    Gemeindeschlüssel,
    neurologie_label,
    label
  ) |>
  as_tibble() |> 
  write_csv(datenpfad_clinics)


image_helper_light(
  filename = filename,
  filepath = imagepath,
  data = data_choropleth,
  images = images_choropleth,
  captions = caption_Karten
)

```

```{r}

istzustand_standorte <- stroke_units_data |>
  filter(
    Fallzahl_OPS_Schlaganfall_max > 5 |
      Fallzahl_ICD_Schlaganfall_max > 10 |
      VN24 == TRUE |
      triangulation_max == TRUE | DSG_Zertifiziert == TRUE
  )

n_standorte_istzustand <- istzustand_standorte |>
  select(Standortnummer) |>
  distinct() |>
  count() |>
  pull()

n_standorte_istzustand_ohne_SU <- istzustand_standorte |>
  filter(triangulation_max == FALSE & is.na(VN24) & is.na(DSG_Zertifiziert)) |>
  select(Standortnummer) |>
  distinct() |>
  count() |>
  pull()

```

Erkennbar auf der Karte sind alle von uns identifizierten Schlaganfall-Versorger. In der grün-blauen Farbgebung sind wie in der vorherigen Karte alle Stroke Units nach unserer [Definition](#sec-methoden-definition-stroke-unit) erkennbar. Zusätzlich sind andere [Schlaganfall-Versorger](#sec-methoden-definition-schlaganfallversorger) in Grau dargestellt. Es lässt sich an- und abwählen, welche Schlaganfall-Versorger auf der Karte angezeigt werden, an der Fahrzeitenberechnung ändert dies nichts. Es werden die Fahrzeiten bis zu allen Schlaganfall-Versorgern dargestellt.

Fährt man mit dem Cursor über einen aufgeführten Klinikstandort, zeigen sich auch hier Details zur Struktur der Versorgung an. Zusätzlich zu jenen bei Karte 1:

- die OPS-Fallzahl an frührehabilitativen Behandlungen am Standort könnte ein Indikator für eine eher rehabilitative Spezialisierung des Standorts sein (er könnte also eher kein Akut-Versorger sein), es handelt sich nicht automatisch um Reha-Behandlungen nach einem Schlaganfall
- ob eine neurologische Abteilung am Standort vorhanden ist 
 
Die durchschnittliche Fahrzeit beträgt in diesem Szenario  rund 9,5 Minuten. In diesem aktuellen Szenario benötigen zwar nur knapp eine halbe Million Menschen länger als 30 Minuten bis zu einem Klinikstandort, der Schlaganfälle versorgt. Sie landen aber wahrscheinlicher in einer Klinik, die Schlaganfälle nicht so gut wie eine Stroke Unit behandeln kann. 

Wenn man davon ausgeht, dass nur Klinikstandorte mit mehr als zehn Schlaganfall-Diagnosen oder 5 Schlaganfall-Komplexbehandlungen in den Qualitätsberichten tatsächlich eine Rolle in der Schlaganfallversorgung spielen, dann nahmen im Jahr 2022 `r format(n_standorte_istzustand, big.mark="", decimal.mark=",")` Klinikstandorte an der Versorgung teil. Abzüglich der vom uns identifizierten Stroke Units nehmen `r format(n_standorte_istzustand_ohne_SU, big.mark=" ", decimal.mark=",")` Klinikstandorte ohne Stroke Unit an der [Schlaganfall-Versorgung](#sec-methoden-definition-schlaganfallversorger) teil. 

Die Karte bildet eher die Versorgungsrealität ab, jedoch mit Einschränkungen: Einige der „grauen“ Klinikstandorte sind reine Reha-Kliniken, die zwar Schlaganfälle im Rahmen einer Frührehabilitation behandeln, aber nicht an der Akutversorgung teilnehmen. In anderen Fällen ist der Schlaganfall erst während eines Klinikaufenthalts aufgetreten und als solcher auch codiert worden, er war aber nicht Hauptaufnahmegrund, sondern Nebendiagnose. Welche der „grauen“ Klinikstandorte tatsächlich Akutversorger sind, ist deshalb nicht eindeutig anhand der verfügbaren Daten zu ermitteln.

Inwieweit eine Klinik eine bessere Schlaganfall-Versorgung bietet als andere, also eine höhere Qualität etwa in Bezug auf Sterberisiko und Funktionsniveau der Behandelten aufweist, ist trotz struktureller Unterschiede der Häuser anhand unserer Daten nicht eindeutig zu bestimmen. Strukturelle Unterschiede sind etwa: Gibt es eine Abteilung für Neurologie? [Nimmt die Klinik an einem Qualitätssicherungsprojekt für Schlaganfall-Behandlungen teil?](https://www.sciencedirect.com/science/article/abs/pii/S1052305723002641){target="_blank"} [Ist die Klinik Teil eines telemedizinischen Netzwerks?](https://pmc.ncbi.nlm.nih.gov/articles/PMC11134988/){target="_blank"} 
Auch innerhalb der Klinikstandorte ohne Stroke Unit gibt es eine [Bandbreite an Qualitätsunterschieden](https://www.sciencedirect.com/science/article/abs/pii/S1052305723002641){target="_blank"}, die wir hier nicht umfassend darstellen können. 

#### Telemedizinische Netzwerke 

In unterversorgten Gebieten ohne Stroke Unit spielen [telemedizinisch vernetzte Kliniken](https://pmc.ncbi.nlm.nih.gov/articles/PMC11134988/){target="_blank"} eine besondere Rolle. 22 telemedizinische Netzwerke umfassen 225 Kooperationskliniken, die von 43 zentralen Stroke Units aus dem Netzwerk beraten werden. Die telemedizinische Beurteilung von und die Therapieempfehlungen für Schlaganfall-Patient:innen und deren zerebraler Bildgebung wird von Ärzt:innen in den Stroke-Unit-Zentren geleistet. Viele dieser Kooperationskliniken sind Kliniken, die Schlaganfälle behandeln, obwohl sie keine neurologische Abteilung haben. Für sie soll unter anderem die telemedizinische neurologische Fachexpertise die Behandlung verbessern. Ungefähr jeder zehnte Schlaganfall wird mit telemedizinischer Hilfe behandelt. 

Die Versorgungsqualität innerhalb dieser 225 Kliniken kann aber trotzdem stark variieren: Einige dieser Kliniken erfüllen die Voraussetzungen einer Stroke Unit nach unseren Kriterien und sind auf unseren Karten erkennbar, andere Kliniken behandeln sehr selten Schlaganfälle oder haben keine Abteilung für Neurologie. Auch die Qualitätssicherungs-Instrumente innerhalb der telemedizinischen Netzwerke sind heterogen. Im Rahmen der geplanten Klinikreform sollen in regional begründeten Einzelfällen auch telemedizinisch vernetzte Kooperationskliniken akute Schlaganfälle versorgen dürfen. 

#### Anteil der Stroke Units an der Schlaganfall-Versorgung 

Im folgenden Diagramm ist dargestellt, welchen Anteil die verschiedenen Klinikstandort-Kategorien an der Schlaganfall-Versorgung haben. Die meisten Schlaganfälle werden bereits in Stroke Units nach unserer Definition behandelt: An den gut 400<span style=„font-size:50%;“> </span>000 codierten ICD-Schlaganfall-Diagnosen haben die Stroke Units einen Anteil von 85 Prozent. Knapp 40 Prozent der Schlaganfälle werden in einem Klinikstandort mit überregionaler Stroke Unit codiert.  
Zwar nehmen `r format(n_standorte_istzustand_ohne_SU, big.mark=" ", decimal.mark=",")` Klinikstandorte ohne Stroke Unit an der Versorgung teil, diese haben mit knapp 60<span style=„font-size:50%;“> </span>000 Fällen aber nur einen Anteil von knapp 15 Prozent an der Gesamtversorgung.  

```{r}
#| label: stacked-barplot-faelle
#| output: true
#| fig-height: 4

filename <- "Barplot_Fallzahlen"

data_to_plot <- 
  stroke_units_data |>
  mutate(
    unsere_definition = case_when(
    (VN24 == TRUE | triangulation_max == TRUE | DSG_Zertifiziert == TRUE) ~ TRUE,
    is.na((VN24 == TRUE | triangulation_max == TRUE | DSG_Zertifiziert == TRUE)) ~ FALSE
    )
  ) |>
  mutate(
    group = case_when(
      Zertifiziert_als %in% c("Überregionale Stroke Unit", "Überregionale Comprehensive Stroke Unit") ~ "überregionale Stroke Unit",
      (Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > 0  &
        Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > coalesce(Fallzahl_OPS_regionale_SU_max, 0) &
        Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > coalesce(Fallzahl_OPS_ueberregionale_SU_max, 0) &
        Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > coalesce(Fallzahl_OPS_andere_SU_ohne_Telekonsildienst_max, 0) &
         unsere_definition == TRUE) ~ "Tele-Stroke-Unit",
      (unsere_definition == FALSE) ~ "keine Stroke Unit",
      TRUE ~ "alle anderen Stroke Units"
    )
  ) |> 
  select(Fallzahl_OPS_Schlaganfall_max,
         Fallzahl_ICD_Schlaganfall_max,
         group) |>
  rename(OPS = Fallzahl_OPS_Schlaganfall_max, ICD = Fallzahl_ICD_Schlaganfall_max) |>
  pivot_longer(
    cols = c("ICD"),
    names_to = "Code",
    values_to = "Fälle"
  ) |>
  group_by(group, Code) |>
  summarise(Fälle = sum(Fälle, na.rm = TRUE)) |>
  ungroup() |>
  group_by(Code) |>
  mutate(Total_Faelle = sum(Fälle),
         # Total cases per 'Code'
         Prozent = (Fälle / Total_Faelle) * 100) |> 
  mutate(group = factor(group, levels = rev(c("überregionale Stroke Unit", "alle anderen Stroke Units", "Tele-Stroke-Unit", "keine Stroke Unit")))) |> 
  ungroup()


p <-
  data_to_plot |>
  write_csv(file.path(imagepath, paste0(filename, ".csv"))) |>
  ggplot(aes(
    x = "",
    y = Fälle,
    fill = group,
    text = paste0(
      "Schlaganfall-Versorger: ",
      group,
      "\n",
      "Fälle: ",
      format(Fälle, big.mark = " ", decimal.mark = ","),
      "\n",
      "Fälle Total: ",
      format(Total_Faelle, big.mark = " ", decimal.mark = ","),
      "\n",
      "Prozent: ",
      format(
        round(Prozent, 2),
        big.mark = " ",
        decimal.mark = ","
      )
    )
  )) +
  geom_bar(position = "stack", stat = "identity") +
  scale_fill_manual(values = marker_colors) +
  coord_flip() +
  labs(y = "Fälle", x = "", title = "Schlaganfälle (nach ICD-Codes)",
       fill = "")

ggplotly_SMC(p, tooltip = c("text"), legende_unten = FALSE) |>
  plotly::layout(#  legend = list(y = -13.5),
    hovermode = "closest")

p |>
  image_helper(filename, imagepath, plotly = TRUE, caption = caption_GBA)

```



### Fahrzeitdifferenzen 

Wie würden sich nun die Fahrzeiten konkret verändern, wenn im Rahmen einer grundlegenden Klinikreform alle akuten Schlaganfall-Patient:innen direkt in Klinikstandorte mit Stroke Unit gebracht würden – entsprechend der Karte 1 dieses Datenreports? Ein Szenario, das sowohl die Regierungskommission für eine moderne und bedarfsgerechte Krankenhausversorgung [empfiehlt](https://www.bundesgesundheitsministerium.de/fileadmin/Dateien/3_Downloads/K/Krankenhausreform/5_Stellungnahme_Potenzialanalyse_bf_Version_1.1.pdf){target="_blank"}, als auch [die aktuelle Leitlinie für die Akuttherapie des Schlaganfalls]( https://register.awmf.org/de/leitlinien/detail/030-046){target="_blank"}. 

Auf der folgenden Karte sind nun die durchschnittlichen Fahrzeitverlängerungen für jede Gemeinde dargestellt. Die Verlängerung entspricht der Differenz der Fahrzeiten aus Karte 1 und 2. Die durchschnittliche Fahrzeitverlängerung beträgt bundesweit nur rund 4,5 Minuten, allerdings gibt es einzelne Gebiete, in denen sie viel länger ist. Ein Beispiel ist das sächsische Weißwasser: Hier beträgt die durchschnittliche Fahrzeitverlängerung 44 Minuten. Hier würde sich die durchschnittliche Fahrzeit von aktuell drei Minuten bis zum Kreiskrankenhaus Weißwasser auf 47 Minuten bis zur nächten Stroke Unit, zum Beispiel in Hoyerswerda, verlängern. 

```{r}
#| label: fahrzeiten-differenz-Datenvorverarbeitung

fahrzeit_differenz <- unsere_definition |>
  left_join(istzustand,
            by = "grid_id",
            suffix = c("_unsere_definition", "_istzustand")) |>
  mutate(fahrzeit_differenz = (sek_Klinik_1_unsere_definition - sek_Klinik_1_istzustand) / 60) |> # länger - kürzer
  group_by(ags_unsere_definition) |>
  summarise(
    weighted_avg_fahrzeit_differenz = sum(fahrzeit_differenz * ew_unsere_definition, na.rm = TRUE) / sum(ew_unsere_definition, na.rm = TRUE),
    total_ew = sum(ew_unsere_definition, na.rm = TRUE)
  ) |>
  inner_join(gemeinden_simplified_2019, by = c("ags_unsere_definition" = "AGS")) |>
  ungroup() |>
  sf::st_as_sf() # ensure that object is a simple-features (sf) object

polygon_data <- fahrzeit_differenz

processed_polygon_data <- polygon_data |>
  mutate(
    pretty_variable_col = format(round(polygon_data[["weighted_avg_fahrzeit_differenz"]],1), big.mark=" ", decimal.mark=","),
    pretty_variable_col_total_ew = format(polygon_data[["total_ew"]], big.mark=" ", decimal.mark=",")
    ) |>
  mutate(
    label = paste0(
      "<strong>", GEN, "</strong>",
      "<br/>Fahrzeit-Differenz in min: ", pretty_variable_col,
      "<br/>Einwohner:innen: ", pretty_variable_col_total_ew
    )
  ) |>
  rowwise() |> # transform rowwise to html tag
  mutate(
    label = HTML(label)
  )

```

```{r}

data_info <- stroke_units_data |>
  filter(
    Fallzahl_OPS_Schlaganfall_max > 5 |
      Fallzahl_ICD_Schlaganfall_max > 10 |
      VN24 == TRUE |
      triangulation_max == TRUE | DSG_Zertifiziert == TRUE
  ) |>
  mutate(
    label = paste0(
    "<strong>",
    ifelse(is.na(Name), Einrichtung_Name, Name), # per default "Name" der DSG-Liste, sonst "Einrichtung_Name" der InEK-Liste
    "</strong>",
    "<br/>",
    "<p>Ort / PLZ: ",
    ifelse(is.na(Ort), Einrichtung_GeoAdresse_Ort, Ort), " / ", ifelse(is.na(Postleitzahl), Einrichtung_GeoAdresse_PLZ, Postleitzahl),
    "<br/>",
    "<p>Fallzahl ICD: ",
    Fallzahl_ICD_Schlaganfall_max,
    "<br/>",
    "Fallzahl OPS: ",
    Fallzahl_OPS_Schlaganfall_max,
    "<br/>",
    "Fallzahl Reha-OPS: ",
    Fallzahl_OPS_Reha_max,
    '<br/></p>',
    "<p>Neurologie: ",
    neurologie_label,
    '</p>',
    "VN24: ",
    VN24_label,
    "<br/>",
    "ICD/OPS-Kriterium: ",
    icd_ops_kriterium_label,
    '<br/>',
    "Zertifiziert als: ",
    Zertifiziert_als_label
  )
  ) |>
  rowwise() |> # transform rowwise to html tag
  mutate(
    label = HTML(label)
  )


data_info <- data_info |>
  mutate(
    unsere_definition = case_when(
    (VN24 == TRUE | triangulation_max == TRUE | DSG_Zertifiziert == TRUE) ~ TRUE,
    is.na((VN24 == TRUE | triangulation_max == TRUE | DSG_Zertifiziert == TRUE)) ~ FALSE
    )
  ) |>
  mutate(
    group = case_when(
      Zertifiziert_als %in% c("Überregionale Stroke Unit", "Überregionale Comprehensive Stroke Unit") ~ "überregionale Stroke Unit",
      (Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > 0  &
        Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > coalesce(Fallzahl_OPS_regionale_SU_max, 0) &
        Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > coalesce(Fallzahl_OPS_ueberregionale_SU_max, 0) &
        Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > coalesce(Fallzahl_OPS_andere_SU_ohne_Telekonsildienst_max, 0) &
         unsere_definition == TRUE) ~ "Tele-Stroke-Unit",
      (unsere_definition == FALSE) ~ "keine Stroke Unit",
      TRUE ~ "alle anderen Stroke Units"
    )
  ) |>
  mutate(
    fillColor = case_when(
      group == "überregionale Stroke Unit" ~ marker_colors[["überregionale Stroke Unit"]],
      group == "alle anderen Stroke Units" ~ marker_colors[["alle anderen Stroke Units"]],
      group == "Tele-Stroke-Unit" ~ marker_colors[["Tele-Stroke-Unit"]],
      group == "keine Stroke Unit" ~ marker_colors[["keine Stroke Unit"]]
    ),
    color = "black",
  ) |>
  mutate(stroke_yes_no = case_when(
    unsere_definition == TRUE ~ "Stroke Units",
    unsere_definition == FALSE ~ "keine Stroke Units"
  ))
```


```{r}

# create a function that maps numeric value to color
binned_palette_differenzen <- colorBin(
  palette = "YlOrRd",
  domain = c(0, max(processed_polygon_data$weighted_avg_fahrzeit_differenz)),
  bins = c(0, 10, 20, 30, 40, 50, 60, Inf),
  na.color = "transparent"
)

colors_differenzen <- binned_palette_differenzen(c(5, 15, 25, 35, 45, 55, 100))

polygon_color_mapping <- binned_palette_differenzen(processed_polygon_data$weighted_avg_fahrzeit_differenz)
```



```{r}
map <- create_base_map(base_map_parameters) |>
  addMapPane("choropleth", zIndex = 400) |>
  map_add_choropleth_layer(
    polygon_data = processed_polygon_data,
    polygon_color_mapping = polygon_color_mapping,
    polygon_label = processed_polygon_data$label,
    choropleth_layer_parameters = choropleth_layer_parameters,
    leaflet_group = "Fahrzeiten-Differenz"
  ) |>
  addMapPane("basemap", zIndex = 500) |>
  addTiles(urlTemplate = "https://tileserver.smc.report/data/all_zoom_levels/{z}/{x}/{y}.png",
         options = pathOptions(pane = "basemap")) |>
  addMapPane("clinics", zIndex = 600) |>
  addCircleMarkers(
    data = data_info,
    label = data_info$label,
    fillColor =  data_info$fillColor,
    color = data_info$color,
    radius = circle_marker_parameters$radius,
    stroke = circle_marker_parameters$stroke,
    weight = circle_marker_parameters$weight,
    fillOpacity = circle_marker_parameters$fillOpacity,
    labelOptions = circle_marker_parameters$labelOptions,
    options = circle_marker_parameters$options,
    group = data_info$stroke_yes_no
  ) |>
  # addLegend(
  #   # choropleth
  #   "bottomleft",
  #   # pal = binned_palette_nur_SU,
  #   colors = choropleth_legend_colors,
  #   values = processed_polygon_data_istzustand$weighted_avg_fahrzeit,
  #   title = HTML("Fahrzeit in min"),
  #   opacity = 1,
  #   labels = c("0-10", "10-20", "20-30", "30-40", "40-50", "50-60", ">60"),
  #   group = "Fahrzeiten-Istzustand"
  # ) |>
  addLegend(
    # choropleth
    "bottomleft",
    # pal = binned_palette_differenzen,
    colors = colors_differenzen,
    values = processed_polygon_data$weighted_avg_fahrzeit_differenz,
    title = HTML("Fahrzeitdifferenz in min"),
    opacity = 1,
    labels = c("0-10", "10-20", "20-30", "30-40", "40-50", "50-60", ">60"),
    group = "Fahrzeiten-Differenz"
  ) |>
  # addLegend(
  #   # choropleth
  #   "bottomleft",
  #   # pal = binned_palette_nur_SU,    
  #   colors = choropleth_legend_colors,
  #   values = processed_polygon_data_nur_SU$weighted_avg_fahrzeit,
  #   title = HTML("Fahrzeit in min"),
  #   opacity = 1,
  #   labels = c("0-10", "10-20", "20-30", "30-40", "40-50", "50-60", ">60"),
  #   group = "Fahrzeiten-Nur SUs"
  # ) |>
  addLegendCustom(
    # markers
    "bottomright",
    colors = unname(marker_colors),
    labels = names(marker_colors),
    title = HTML("Schlaganfall-Versorger"),
    sizes = 15,
    opacity = 1
    # group = "markers"
  ) |>
  addResetMapButton() |>
  addSearchFeatures(
    targetGroups  = c("Fahrzeiten-Differenz"),
    options = searchFeaturesOptions(
      zoom = 10,
      openPopup = FALSE,
      autoCollapse = TRUE,
      position = "topright",
      marker = list(
        icon = NULL,
        animate = TRUE,
        circle = list(
          radius = 10,
          weight = 3,
          color = "orange",
          stroke = TRUE,
          fill = FALSE
        )
      )
    )
  ) |>
  leaflet.extras::addFullscreenControl(position = "topleft")

    map <- addGroupedLayersControl(
      map,
      overlayGroups = list("Schlaganfall-Versorger" = c("Stroke Units", "keine Stroke Units")),
      position = c("bottomright"),
      options = groupedLayersControlOptions(
        groupCheckboxes = FALSE,
        collapsed = FALSE,
        groupsCollapsable = FALSE,
        sortLayers = FALSE,
        sortGroups = FALSE,
        sortBaseLayers = FALSE,
        exclusiveGroups = "Gemeinden"
      )
    ) |>
    hideGroup("Fahrzeiten-Istzustand") |>
      hideGroup("Fahrzeiten-Nur SUs") |>
        hideGroup("keine Stroke Units")

map

filename <- "Differenz_Fahrzeiten"

data_choropleth <- tibble(
  fileformat = c("csv", "csv"),
  filename_suffix = c("Kliniken", "Fahrtzeiten")
)
images_choropleth <- tibble(
  fileformat = c("html"),
  filename_suffix = c("")
)

htmlpfad <- file.path(imagepath, paste0(filename, ".html"))
datenpfad_clinics <- file.path(imagepath, paste0(filename, "_Kliniken.csv"))
datenpfad_distance <- file.path(imagepath, paste0(filename, "_Fahrtzeiten.csv"))

mapshot(map, url=htmlpfad)

processed_polygon_data |>
  select(
    ags_unsere_definition,
    weighted_avg_fahrzeit_differenz,
    total_ew,
    BEZ,
    GEN,
    NUTS,
    BEM,
    OBJECTID,
    EWZ,
    KFL,
    pretty_variable_col,
    pretty_variable_col_total_ew,
    label
  ) |> 
  as_tibble() |> 
  write_csv(datenpfad_distance)

data_info |>
  select(
    Standortnummer, 
    Zertifiziert_als,
    VN24, VN24_label,
    Bezeichnung, 
    ReferenzKrankenhaus_IK,
    StandortId,
    lat,
    lon,
    Einrichtung_GeoAdresse_PLZ,
    Einrichtung_GeoAdresse_Ort,
    Einrichtung_GeoAdresse_Straße,
    Einrichtung_GeoAdresse_Hausnummer,
    Einrichtung_GeoAdresse_AdressZusatz,
    Gemeindeschlüssel,
    neurologie_label,
    label
  ) |>
  as_tibble() |> 
  write_csv(datenpfad_clinics)


image_helper_light(
  filename = filename,
  filepath = imagepath,
  data = data_choropleth,
  images = images_choropleth,
  captions = caption_Karten
)

```
Im Menü lassen sich die dargestellten Klinikstandorte an- und abwählen: Stroke Units und alle anderen Schlaganfall-Versorger. Wählt man zum Beispiel die Schlaganfall-Versorger ohne Stroke Units aus, kann man Klinikstandorte identifizieren, die statt Stroke Units in unterversorgten Gebieten angefahren werden könnten. 

Größere Fahrzeitverlängerungen gäbe es auch hier zum Beispiel in der Region Altmark im nördlichen Sachsen-Anhalt. So würde es für die 23<span style=„font-size:50%;“> </span>000 Einwohner:innen in Salzwedel im Durchschnitt knapp 43 Minuten länger dauern, um zur nächsten Stroke Unit zu fahren, als ins Krankenhaus Salzwedel, wo es keine Stroke Unit gibt. Im Krankenhaus Salzwedel wurden im Jahr 2022 insgesamt 129 Schlaganfälle codiert – Fälle, die womöglich auch in die Stroke Unit nach Uelzen hätten gefahren werden können. Die längere Fahrzeit nach Uelzen könnte hier dazu geführt haben, dass die Schlaganfall-Fälle ins näherlegende Klinikum in Salzwedel transportiert wurden. 

In den niedersächsischen Gemeinden Bassum, Twistringen und Sulingen würde man etwa eine halbe Stunde länger zur nächsten Stroke Unit, beispielsweise in Bremen, brauchen. Klinikstandorte in dieser Region, die Schlaganfall-Diagnosen melden, obwohl sie keine Stroke Unit haben, sind etwa das Klinikum Bassum, die Klinik Sulingen und das Krankenhaus Johanneum. 

Solche Fahrzeitdifferenzen sind möglicherweise der Grund, dass in der Realität bisher nicht alle Schlaganfälle in Kliniken mit einer Stroke Unit transportiert werden. Die Verteilung von Klinikstandorten ohne Stroke Unit in Gebieten, wo es keine große Fahrzeitverlängerung gibt, deutet aber darauf hin, dass es auch andere Gründe dafür geben könnte. Es könnte sein, dass die Stroke Units in diesen eigentlich gut angebundenen Gebieten nicht ausreichend Kapazitäten haben. 

### Thrombektomien 

Auf der folgenden Karte sind alle Klinikstandorte mit Stroke Unit dargestellt, die Thrombektomien der intrakraniellen Gefäße in ihren Qualitätsberichten angegeben haben. Die Thrombektomie ist eine wichtige Behandlungsmethode, die bei bestimmten Arten des ischämischen Schlaganfalls, bei dem ein Blutgerinnsel ein Gefäß verstopft, [Vorteile für das Funktionsniveau nach dem Schlaganfall (Outcome) der Patient:innen](https://www.aerzteblatt.de/archiv/173139/Mechanische-Thrombektomie-bei-Schlaganfall){target="_blank"} bieten kann. Zudem haben wir die Fahrzeiten bis zum nächstgelegenen Klinikstandstandort mit Stroke Unit und Thrombektomie-Möglichkeit visualisiert. Nicht alle der aufgeführten Klinikstandorte bieten allerdings rund um die Uhr Thrombektomien an. Nur bei überregionalen Stroke Units ist dies garantiert.

Würden im Falle eines Schlaganfalls, bei dem eine Thrombektomie infrage kommen könnte, nur noch diese Kliniken von Rettungsdiensten angefahren, betrüge die durchschnittliche Fahrzeit zu solch einem Standort rund 18 Minuten. Etwa drei Millionen Menschen würden länger als 45 Minuten bis zu einer Stroke Unit brauchen, die Thrombektomien durchführen kann.


```{r}
#| label: fahrzeiten-thrombektomie-Datenvorverarbeitung
#| output: false

data_to_plot <- thrombektomie

# durchschnittliche (Einwohner-gewichtete) Fahrzeit pro Gemeinde
polygon_data <- data_to_plot |>
  mutate(fahrzeit_in_min = sek_Klinik_1 / 60) |>
  group_by(ags) |>
  summarise(weighted_avg_fahrzeit = sum(fahrzeit_in_min * ew, na.rm = TRUE) / sum(ew, na.rm = TRUE),
            total_ew = sum(ew, na.rm = TRUE)) |>
  inner_join(gemeinden_simplified_2019, by = c("ags" = "AGS")) |>
  ungroup() |>
  sf::st_as_sf() # ensure that object is a simple-features (sf) object

processed_polygon_data <- polygon_data |>
  mutate(
    pretty_variable_col = format(round(polygon_data[["weighted_avg_fahrzeit"]],1), big.mark=" ", decimal.mark=","),
    pretty_variable_col_total_ew = format(polygon_data[["total_ew"]], big.mark=" ", decimal.mark=",")
    ) |>
  mutate(
    label = paste0(
      "<strong>", GEN, "</strong>",
      "<br/>Fahrzeit in min: ", pretty_variable_col,
      "<br/>Einwohner:innen: ", pretty_variable_col_total_ew
    )
  ) |>
  rowwise() |> # transform rowwise to html tag
  mutate(
    label = HTML(label)
  )


```

```{r}
#| label: fahrzeiten-thrombektomie-Colormap
#| output: false

## Get colors for these values using our custom palette
colors_thrombektomie <- rev(sequential_hcl(n=7, palette = "Reds 2"))
# hcl_wizard()

# create a function that maps numeric value to color
binned_palette_thrombektomie <- colorBin(
  palette = colors_thrombektomie,
  domain = c(0, max(processed_polygon_data$weighted_avg_fahrzeit)),
  bins = c(0, 20, 40, 60, 80, 100, 120, Inf),
  na.color = "transparent"
)

polygon_color_mapping <- binned_palette_thrombektomie(processed_polygon_data$weighted_avg_fahrzeit)
```


```{r}
#| label: karte-thrombektomien-Tooltip
#| output: true

data_info <- stroke_units_data |>
  filter(VN24 == TRUE |
           triangulation_max == TRUE | DSG_Zertifiziert == TRUE) |>
  filter(Fallzahl_OPS_thrombektomie_max > 0) |>
  mutate(
    label = paste0(
    "<strong>",
    ifelse(is.na(Name), Einrichtung_Name, Name), # per default "Name" der DSG-Liste, sonst "Einrichtung_Name" der InEK-Liste
    "</strong>",
    "<br/>",
    "<p>Ort / PLZ: ",
    Einrichtung_GeoAdresse_Ort, " / ", Einrichtung_GeoAdresse_PLZ,
    "<br/>",
    "<p>Fallzahl Thrombektomie: ",
    Fallzahl_OPS_thrombektomie_max,
    "<br/>",
    "<p>Fallzahl ICD: ",
    Fallzahl_ICD_Schlaganfall_max,
    "<br/>",
    "Fallzahl OPS: ",
    Fallzahl_OPS_Schlaganfall_max,
    '<br/></p>',
    "VN24: ",
    VN24_label,
    "<br/>",
    "ICD/OPS-Kriterium: ",
    icd_ops_kriterium_label,
    '<br/>',
    "Zertifiziert als: ",
    Zertifiziert_als_label
    )
  ) |>
  rowwise() |> # transform rowwise to html tag
  mutate(
    label = HTML(label)
  )


data_info <- data_info |>
  mutate(
    unsere_definition = case_when(
    (VN24 == TRUE | triangulation_max == TRUE | DSG_Zertifiziert == TRUE) ~ TRUE,
    is.na((VN24 == TRUE | triangulation_max == TRUE | DSG_Zertifiziert == TRUE)) ~ FALSE
    )
  ) |>
  mutate(
    group = case_when(
      Zertifiziert_als %in% c("Überregionale Stroke Unit", "Überregionale Comprehensive Stroke Unit") ~ "überregionale Stroke Unit",
      (Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > 0  &
        Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > coalesce(Fallzahl_OPS_regionale_SU_max, 0) &
        Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > coalesce(Fallzahl_OPS_ueberregionale_SU_max, 0) &
        Fallzahl_OPS_andere_SU_mit_Telekonsildienst_max > coalesce(Fallzahl_OPS_andere_SU_ohne_Telekonsildienst_max, 0) &
         unsere_definition == TRUE) ~ "Tele-Stroke-Unit",
      (unsere_definition == FALSE) ~ "keine Stroke Unit",
      TRUE ~ "alle anderen Stroke Units"
    )
  ) |>
  mutate(
    fillColor = case_when(
      group == "überregionale Stroke Unit" ~ marker_colors[["überregionale Stroke Unit"]],
      group == "alle anderen Stroke Units" ~ marker_colors[["alle anderen Stroke Units"]],
      group == "Tele-Stroke-Unit" ~ marker_colors[["Tele-Stroke-Unit"]],
      group == "keine Stroke Units" ~ marker_colors[["keine Stroke Unit"]]
    ),
    color = "black", # to mark that they are special - can perform a thrombektomy
  ) |>
  mutate(stroke_yes_no = case_when(
    unsere_definition == TRUE ~ "Stroke Units",
    unsere_definition == FALSE ~ "keine Stroke Units"
  ))

```

```{r}
#| label: karte-thrombektomien

map <- create_base_map(base_map_parameters) |>
  addMapPane("choropleth", zIndex = 400) |>
  map_add_choropleth_layer(
    polygon_data = processed_polygon_data,
    polygon_color_mapping = polygon_color_mapping,
    polygon_label = processed_polygon_data$label,
    choropleth_layer_parameters = choropleth_layer_parameters,
    leaflet_group = "Fahrzeiten"
  ) |>
  addMapPane("basemap", zIndex = 500) |>
  addTiles(urlTemplate = "https://tileserver.smc.report/data/all_zoom_levels/{z}/{x}/{y}.png",
         options = pathOptions(pane = "basemap")) |>
  addMapPane("clinics", zIndex = 600) |>
  addCircleMarkers(
    data = data_info,
    label = data_info$label,
    fillColor =  data_info$fillColor,
    color = data_info$color,
    radius = circle_marker_parameters$radius,
    stroke = circle_marker_parameters$stroke,
    weight = circle_marker_parameters$weight,
    fillOpacity = circle_marker_parameters$fillOpacity,
    labelOptions = circle_marker_parameters$labelOptions,
    options = circle_marker_parameters$options,
    group = data_info$group
  ) |>
  addLegend(
    # choropleth
    "bottomleft",
    colors = colors_thrombektomie,
    values = processed_polygon_data$weighted_avg_fahrzeit,
    title = HTML("Fahrzeit in min"),
    labels = c("0-20", "20-40", "40-60", "60-80", "80-100", "100-120", ">120"),
    opacity = 1
  ) |>
  addLegendCustom(
    # markers
    "bottomright",
    colors = c(marker_colors["überregionale Stroke Unit"], marker_colors["alle anderen Stroke Units"], marker_colors["Tele-Stroke-Unit"]),
    labels = c("überregionale Stroke Unit", "alle anderen Stroke Units", "Tele-Stroke-Unit"),
    title = HTML("Stroke Units"),
    sizes = 15,
    opacity = 1
    # group = "markers"
  ) |>
  addResetMapButton() |>
  addSearchFeatures(
    targetGroups  = c("Fahrzeiten", "Thrombektomie"),
    options = searchFeaturesOptions(
      zoom = 10,
      openPopup = FALSE,
      autoCollapse = TRUE,
      position = "topright",
      marker = list(
        icon = NULL,
        animate = TRUE,
        circle = list(
          radius = 10,
          weight = 3,
          color = "orange",
          stroke = TRUE,
          fill = FALSE
        )
      )
    )
  ) |>
  leaflet.extras::addFullscreenControl(position = "topleft")

    map <- addGroupedLayersControl(
      map,
      overlayGroups = list("Stroke Units" = c("überregionale Stroke Unit", "Tele-Stroke-Unit", "alle anderen Stroke Units")),
      position = c("bottomright"),
      options = groupedLayersControlOptions(
        groupCheckboxes = FALSE,
        collapsed = FALSE,
        groupsCollapsable = FALSE,
        sortLayers = FALSE,
        sortGroups = FALSE,
        sortBaseLayers = FALSE,
        exclusiveGroups = character(0)
      )
    )

map

filename <- "Fahrzeiten_Thrombektomien"

data_choropleth <- tibble(
  fileformat = c("csv", "csv"),
  filename_suffix = c("Kliniken", "Fahrtzeiten")
)
images_choropleth <- tibble(
  fileformat = c("html"),
  filename_suffix = c("")
)

htmlpfad <- file.path(imagepath, paste0(filename, ".html"))
datenpfad_clinics <- file.path(imagepath, paste0(filename, "_Kliniken.csv"))
datenpfad_distance <- file.path(imagepath, paste0(filename, "_Fahrtzeiten.csv"))

mapshot(map, url=htmlpfad)

processed_polygon_data |>
  select(
    ags,
    weighted_avg_fahrzeit,
    total_ew,
    BEZ,
    GEN,
    NUTS,
    BEM,
    OBJECTID,
    EWZ,
    KFL,
    pretty_variable_col,
    pretty_variable_col_total_ew,
    label
  ) |> 
  as_tibble() |> 
  write_csv(datenpfad_distance)

data_info |>
  select(
    Standortnummer, 
    Zertifiziert_als,
    VN24, VN24_label,
    Bezeichnung, 
    ReferenzKrankenhaus_IK,
    StandortId,
    lat,
    lon,
    Einrichtung_GeoAdresse_PLZ,
    Einrichtung_GeoAdresse_Ort,
    Einrichtung_GeoAdresse_Straße,
    Einrichtung_GeoAdresse_Hausnummer,
    Einrichtung_GeoAdresse_AdressZusatz,
    Gemeindeschlüssel,
    neurologie_label,
    label
  ) |>
  as_tibble() |> 
  write_csv(datenpfad_clinics)


image_helper_light(
  filename = filename,
  filepath = imagepath,
  data = data_choropleth,
  images = images_choropleth,
  captions = caption_Karten
)
```


Bei einem akuten Schlaganfall kommen in der Regel zwei Therapiewege infrage: die Thrombolyse und die Thrombektomie, die auch kombiniert werden können. Bei der Thrombolyse wird das Blutgerinnsel mit Medikamenten aufgelöst. Sie kommt grundsätzlich in den ersten viereinhalb Stunden nach Symptombeginn infrage und kann sehr große Blutgerinnsel nicht immer auflösen. 

Bei einer [Thrombektomie](https://www.thieme-connect.de/products/ejournals/pdf/10.1055/a-0970-2871.pdf){target="_blank"} entfernt man das Blutgerinnsel, was den Schlaganfall auslöst, mechanisch und minimalinvasiv, damit das Blut wieder durch das Hirngefäß fließen kann, die Gehirnzellen wieder mit Blut und Sauerstoff versorgt werden.  Die Thrombektomie kann auch größere Blutgerinnsel entfernen und kommt auch noch nach dem Zeitfenster von viereinhalb Stunden infrage. Die Thrombektomie [verbessert](https://www.aerzteblatt.de/archiv/173139/Mechanische-Thrombektomie-bei-Schlaganfall){target="_blank"} das Funktionsniveau der Patient:innen im Alltag nach dem Schlaganfall und kann den Behinderungsgrad reduzieren. Etwa sechs Prozent der ischämischen Schlaganfall-Patient:innen wurden im Jahr 2023 in Deutschland mit einer mechanischen Thrombektomie behandelt, nämlich 16<span style=„font-size:50%;“> </span>500, was aus [Daten der Deutschen Gesellschaft für Neuroradiologie](https://www.drg.de/de-DE/10495/minimalinvasive-behandlungen-beim-schlaganfall/){target="_blank"} hervorgeht.

Nicht alle Patient:innen mit Schlaganfall eignen sich für eine Thrombektomie: Dafür muss ein ischämischer Schlaganfall vorliegen, bei dem ein größeres Hirngefäß durch ein Blutgerinnsel verlegt ist. Zusätzlich spielt der zeitliche Faktor eine Rolle: In den sechs Stunden nach Symptombeginn ist eine Thrombektomie [empfohlen](https://register.awmf.org/assets/guidelines/030-046l_S2e_Akuttherapie-des-ischaemischen-Schlaganfalls_2022-11-verlaengert.pdf){target="_blank"}, in manchen Fällen bis zu 24 Stunden, wenn noch rettbares Hirngewebe vorliegt. 

Der Anteil der Schlaganfälle, die sich eignen, steigt jedoch, da die Evidenz steigt, dass in manchen Fällen auch bis zu 24 Stunden nach Symptombeginn, bei [sehr großen Schlaganfällen]( https://www.nejm.org/doi/pdf/10.1056/NEJMoa2214403){target="_blank"} oder bei [Menschen über 80 Jahren](https://pubmed.ncbi.nlm.nih.gov/26898852/){target="_blank"} eine Thrombektomie Vorteile für deren Funktionsniveau nach dem Schlaganfall bringt. Künftig sollten möglicherweise geeignete Patient:innen also vermehrt Zugang zur Möglichkeit einer Thrombektomie haben. Dazu gibt es unter anderem folgende [Konzepte](https://pmc.ncbi.nlm.nih.gov/articles/PMC7568974/#sec5){target="_blank"}: 

- „Mothership“: Zuweisung des Schlaganfalls direkt in eine Stroke Unit mit Möglichkeit zur Thrombektomie, Vorteil: weniger Zeitverlust bis zur Thrombektomie, Nachteil: mögliche Behandlungsverzögerung bei der Thrombolyse, weil erst bei Ankunft im Mothership eine Thrombolyse gestartet werden könnte
- „Drip-and-Ship“: Zuweisung des Schlaganfalls in eine näher gelegene Stroke Unit ohne Möglichkeit zur Thrombektomie, dort Diagnostik und Einleitung einer Thrombolysetherapie, Transport in eine Stroke Unit mit Möglichkeit zur Thrombektomie, Vorteil: weniger Zeitverlust bis zur Diagnose und Thrombolyse, Nachteil: Zeitverlust bis zur Thrombektomie wegen der Verlegung

Bei möglicherweise geeigneten Schlaganfällen sind laut [Modellberechnungen](https://www.ahajournals.org/doi/10.1161/STROKEAHA.119.027512?url_ver=Z39.88-2003&rfr_id=ori:rid:crossref.org&rfr_dat=cr_pub%20%200pubmed){target="_blank"} gewisse Behandlungsverzögerungen von bis zu 50 Minuten durch längere Fahrzeiten in Thrombektomie-Zentren vertretbar. 

Laut aktuellen Leitlinien könnte eine direkte Zuweisung in eine Thrombektomie-SU („Mothership“) bei einer Fahrzeit unter 30 bis 45 Minuten in Ballungsgebieten und ansonsten das „Drip-and-Ship“-Konzept bevorzugt werden. 

Alternative Überlegungen sind ein vermehrter Einsatz der Luftrettung in unterversorgten Gebieten oder ein Drive-The-Doctor/Fly-The-Doctor-Konzept, bei denen die notwendigen Ärzt:innen in die Klinik gebracht werden, in der der/die Patient:in liegt. 

Zusammenfassend ist eine direkte Zuweisung in eine Thrombektomie-Stroke-Unit bei Verdacht auf einen großen ischämischen Schlaganfall ein diskutiertes Szenario, konkrete Empfehlungen für tolerierbare Fahrzeitverlängerungen gibt es allerdings nicht. 

Ein Beispiel: In der Stadt Templin in Brandenburg fahren die gut 15<span style=„font-size:50%;“> </span>000 Einwohner:innen im Durchschnitt 5 Minuten bis zur Stroke Unit in Templin, die telemedizinisch vernetzt ist. Würde man Schlaganfälle, die wahrscheinlich von einer Thrombektomie profitieren, direkt in die nächstgelegene Stroke Unit mit der Möglichkeit zur Thrombektomie in Eberswalde transportieren, würde die reine Fahrt im Mittel 60 Minuten dauern – eine Fahrzeitverlängerung von 54 Minuten. Mehr als laut Modellberechnungen in Kauf genommen werden kann. Ein „Mothership“-Konzept ist hier ohne Einsatz der Luftrettung nicht unbedingt möglich, auch schwere Schlaganfälle könnten in eine näher gelegene Stroke Unit ohne Thrombektomiemöglichkeit gebracht werden. 

### Methoden / Limitationen 

Wie das SMC methodisch vorgegangen ist und welche Limitationen dieser Report hat, das wird im folgenden Kapitel erläutert. Vorweg ein Disclaimer: Die Datengrundlage ist keinesfalls zufriedenstellend, eine Annäherung an die Realität ist allerdings möglich. Die Datenbasis wurde zudem mit Forschenden ausführlich diskutiert und Plausibilitätschecks unterzogen. 

#### Was ist eine Klinikstandort? {#sec-methoden-krankenhausstandort} 

```{r}
#| label: anzahl-krankehaeuser
#| output: false

# Standorte

n_unique_haupt_ik <- Krankenhaeuser |>
  distinct(HauptIK) |>
  count() |>
  pull()

n_unique_referenz_ik <- Standorte |>
  distinct(ReferenzKrankenhaus_IK) |>
  count() |>
  pull()

n_unique_standortnummer <- Standorte |>
  distinct(Einrichtung_Standortnummer) |>
  count() |>
  pull()
```

Im Rahmen der Krankenhausreform kommuniziert das [Gesundheitsministerium](https://www.bundesgesundheitsministerium.de/themen/krankenhaus/krankenhausreform/faq-krankenhausreform.html){target="_blank"}, dass es rund 1700 Krankenhäuser in Deutschland gibt. Der Begriff Krankenhaus meint jedoch nicht ein einzelnes Gebäude: Ein Krankenhaus nach Definition des Gesundheitsministeriums kann auf mehrere Standorte verteilt sein.  

Für eine Erreichbarkeitsanalyse sind diese einzelnen Standorte relevant. Aktuell verzeichnet das [Institut für das Entgeltsystem im Krankenhaus (InEK)](https://krankenhausstandorte.de/login){target="_blank"} `r format(n_unique_standortnummer, big.mark="", decimal.mark=",")` Standorte. Hierbei ist anzumerken, dass nicht alle Standorte für alle Fragen relevant sind: Ein Beispiel sind Rehaeinrichtungen, wie [diese Klinik](https://www.rehanova.de/home){target="_blank"}, die keine Rolle in der Schlaganfall-Akutversorgung spielt.

Es gibt leider kein einfaches Maß, um alle relevanten Klinikstandorte zu identifizieren. Aus diesem Grund verzichten wir in diesem Report auf die Betrachtung einer Grundgesamtheit aller Krankenhäuser, sondern betrachten lediglich die für unsere Fragestellung relevanten Klinikstandorte. 


#### Definition Stroke Unit {#sec-methoden-definition-stroke-unit} 

```{r}
#| label: definition-stroke-unit
#| output: false



n_stroke_units_dsg <- stroke_units_data |>
  filter(DSG_Zertifiziert == TRUE) |>
  nrow()

n_stroke_units_triangulation_min <- stroke_units_data |>
  filter(triangulation_min == TRUE) |>
  nrow()

n_stroke_units_triangulation_max <- stroke_units_data |>
  filter(triangulation_max == TRUE) |>
  nrow()

n_stroke_units_VN24 <- stroke_units_data |>
  filter(VN24 == TRUE) |>
  nrow()

n_stroke_units_VN24_triangulation <- stroke_units_data |>
  filter(VN24 == TRUE | triangulation_max == TRUE) |>
  nrow()

n_stroke_units_VN24_triangulation_dsg <- stroke_units_data |>
  filter(VN24 == TRUE | triangulation_max == TRUE | DSG_Zertifiziert == TRUE) |>
  nrow()
```

 „Stroke Unit“ ist kein geschützter Begriff. Als Goldstandard für die Definition einer Stoke Unit gilt für das SMC die Zertifizierung der [Deutschen Schlaganfall-Gesellschaft (DSG)](https://www.dsg-info.de/){target="_blank"}. Die DSG definiert die Anforderungen an eine Stroke Unit in einem [Zertifizierungsverfahren](https://www.dsg-info.de/zertifizierung/){target="_blank"}. Die [Liste der zertifizierten Krankenhausstandorte der DSG](https://www.dsg-info.de/){target="_blank"} bietet also bereits eine gute Grundlage.  

Doch nicht jede Klinik, die faktisch eine Stroke Unit betreibt, ist auch von der DSG zertifiziert. So ist beispielsweise die Stroke Unit der Uniklinik Rostock nicht zertifiziert, erfüllt aber sehr wohl wichtige Kriterien. Die Klinikbetreiber können sich bewusst gegen eine Zertifizierung entscheiden. Um auch Kliniken mit nicht zertifizierten Stroke Units in unserer Analyse mit abzubilden, reichern wir die DSG-Liste mit zusätzlichen Daten aus den Qualitätsberichten der Krankenhäuser des Jahres 2022 an den Gemeinsamen Bundesausschuss (GB-A), die auf dessen [Webseite](https://qb-referenzdatenbank.g-ba.de/#/suche){target="_blank"} bereitgestellt werden, an: 

Zum einen beziehen wir Klinikstandorte in die Definition mit ein, die 

- mindestens 250 entsprechende ICD‑Diagnosen (I60; I61; I63; I64; G45 ausgenommen G45.4) und 
- mindestens 125 relevante OPS‑codierte Prozeduren (OPS 8‑981; 8‑98b) 

angegeben haben (diese Kriterien stammen aus der [Fünften Stellungnahme der Regierungskommission für eine moderne und bedarfsgerechte Krankenhausversorgung](https://www.bundesgesundheitsministerium.de/fileadmin/Dateien/3_Downloads/K/Krankenhausreform/5_Stellungnahme_Potenzialanalyse_bf_Version_1.1.pdf){target="_blank"}). 

Zum anderen beziehen wir Klinikstandorte mit ein, die in der Auswahlliste des medizinischen Leistungsangebots den Code „VN24“ (Stroke Unit) nennen. Ob sich hinter dieser Selbstangabe tatsächlich eine Stroke Unit mit ausreichend Strukturmerkmalen verbirgt oder nicht und wie gut die Behandlungsqualität dort ist, ist unter Forschenden im Feld umstritten. 50 Kliniken geben „VN24“ an und erfüllen keines unserer anderen Kriterien, einige davon besitzen aber weder eine Neurologie noch weisen sie unsere Mindestfallzahlen auf oder codieren relevante OPS-Codes. Die Kliniken erfüllen also einige Strukturmerkmale nicht. Wir haben uns dennoch dafür entschieden, alle Kliniken, die mit „VN24“ selbst eine Stroke Unit angeben, auch als solche zu
klassifizieren.

Weitere Möglichkeiten der Ermittlung einer potenziellen Stroke Unit haben wir außer Acht gelassen. So wurde der Code „SN05“ aus den Modulen der Notfallversorgung nicht berücksichtigt und auch Zertifizierungen der Länder (angegeben über die externe Qualitätssicherung) wurden nicht ausgelesen. 

Damit ergibt sich ein Set an Klinikstandorten, die mit folgendem Venn-Diagramm veranschaulicht werden kann. 

```{r}
#| label: venn-diagramm-definition-stroke-unit
#| output: true
#| fig-height: 6

filename <- "Venn_Diagramm_Stroke_Units"

x <- list(
    DSG = stroke_units_data |>
      filter(DSG_Zertifiziert == TRUE) |>
      pull(Standortnummer),
    "ICD/OPS" = stroke_units_data |>
      filter(triangulation_max == TRUE) |>
      pull(Standortnummer),
    VN24 = stroke_units_data |>
      filter(VN24 == TRUE) |>
      pull(Standortnummer)
  )

venn <- ggVennDiagram::Venn(x)
data <- ggVennDiagram::process_data(venn)

p <- ggplot() +
  # 1. Region count layer with custom fill colors
  geom_polygon(aes(X, Y, fill = id, group = count, text = name),
               data = venn_regionedge(data),
               color = "black",            # Edge color for region
               fill = "#f4f2d2", # smc-gold-100
               text = venn_regionedge(data)$name) +         # Fill color for region
  # 2. Set edge layer with custom color
  geom_path(aes(X, Y, color = id, group = id),
            data = venn_setedge(data),
            color = "black",
            show.legend = FALSE) +
  # 3. Set label layer
  geom_text(aes(X, Y, label = name),
            data = venn_setlabel(data),
            color = "black") +            # Text color for set labels
  # # 4. Region label layer
  # geom_label(aes(X, Y, label = count),
  #            data = venn_regionlabel(data),
  #            color = "white",             # Text color for region labels
  #            fill = "black") +         # Background color for region labels
  # Add text on top of the rectangle
  geom_text(aes(X, Y, label = count, text = name),
            data = venn_regionlabel(data),
            color = "black") +
  coord_equal() +
  # labs(title = "Venn-Diagramm: Stroke Units") +
  # Manually remove axes and grid lines without theme()
  scale_x_continuous(breaks = NULL) +
  scale_y_continuous(breaks = NULL) +
  xlab(NULL) + ylab(NULL)

p_plotly <- ggplotly_SMC(p, tooltip = "text")

# Disable tooltips on the geom_path trace by modifying the `hoverinfo` attribute
for (i in seq_along(p_plotly$x$data)) {
  if (p_plotly$x$data[[i]]$type == "scatter" && p_plotly$x$data[[i]]$mode == "lines") {
    p_plotly$x$data[[i]]$hoverinfo <- "none"
  }
}

p_plotly

p |>
  image_helper(filename, imagepath, plotly = TRUE, caption = caption_GBA_DSG, csv_opt = FALSE)

```

#### Definition eines schlaganfallversorgenden Klinikstandorts ohne „Stroke Unit“ {#sec-methoden-definition-schlaganfallversorger}

Wir beziehen Klinikstandorte in die Definition mit ein, die 

- mindestens zehn entsprechende ICD‑Diagnose (I60; I61; I63; I64; G45 ausgenommen G45.4) oder 
- mindestens fünf relevante OPS‑codierte Prozeduren (OPS 8‑981; 8‑98b) 

angegeben haben 


#### Limitationen bei der Definition eines schlaganfallversorgenden Klinikstandorts 

Entsprechende ICD‑Diagnosen (I60; I61; I63; I64; G45 ausgenommen G45.4) können nicht nur bei einer Aufnahme eines akuten Schlaganfalls codiert werden. Beispielsweise wird dieser Code auch von Standorten codiert, die Schlaganfall-Frührehabilitationen durchführen und gar nicht an der Akutversorgung teilnehmen. Ein weiteres Beispiel sind Schlaganfälle, die während des Klinikaufenthalts aufgetreten sind. Durch diese beispielhaften Limitationen wird klar, dass nicht alle von uns dargestellten Standorte tatsächlich an der Akutversorgung des Schlaganfalls teilnehmen. Es gibt jedoch keine sichere Möglichkeit, diese anhand der vorliegenden Datengrundlage zu identifizieren. Fahrzeiten zu den schlaganfallversorgenden Kliniken zeigen deswegen nur eingeschränkt den nächstgelegenen Standort für eine tatsächliche Akutversorgung an. Deswegen kann auch die Fahrzeitdifferenz nur bedingt darstellen, wie sich Fahrzeiten tatsächlich im Einzelfall verändern. 

Um im Einzelfall Informationen über die Struktur und die mögliche Rolle als Akutversorger eines Standorts zu erhalten, geben wir folgende Merkmale an: 

- Fälle entsprechender ICD‑Diagnosen (I60; I61; I63; I64; G45 ausgenommen G45.4) 
- Fälle relevanter OPS‑codierter Prozeduren (OPS 8‑981; 8‑98b) der Schlaganfall-Komplexbehandlung 
- Fälle OPS‑codierter Prozeduren (OPS 8-550; 8-552; 8-559) der Frührehabilitation 
- Angabe des Fachabteilungsschlüssels „2800“ (Neurologie) und „2856“ (Neurologie/SP Schlaganfallpatienten (Stroke units)) in den Qualitätsberichten 
- Angabe des Codes „VN24“ (Stroke Unit) in den Qualitätsberichten 
- OPS/ICD-Kriterium: Angabe von mindestens 250 entsprechende ICD‑Diagnosen (I60; I61; I63; I64; G45 ausgenommen G45.4) und mindestens 125 relevante OPS‑codierte Prozeduren (OPS 8‑981; 8‑98b) in den Qualitätsberichten 
- Zertifizierungsstatus nach DSG 

#### Definition einer Stroke Unit mit Möglichkeit zur Thrombektomie 

Wir beziehen Klinikstandorte in die Definition mit ein, die 

- unserer Definition von Stroke Unit entsprechen und 
- relevante OPS‑codierte Prozeduren (8-836.80 Thrombektomie: Gefäße intrakraniell) angegeben haben 

Hierbei ist zu beachten, dass auch andere OPS-Codes bei Durchführung einer Thrombektomie beim Schlaganfall angewendet werden könnten. Die angegebene Zahl der Thrombektomien auf der Karte entspricht also nicht der Anzahl aller Thrombektomien für Schlaganfälle, sondern nur der Anzahl an angegebenen 8-836.80 OPS-Codes. Dies dient allein zur Identifizierung der relevanten Klinikstandorte. 

#### Limitationen bei der Definition einer Stroke Unit mit Thrombektomiemöglichkeit

Wir haben uns dazu entschieden, keine Mindestfallzahl bei den Thrombektomien anzusetzen. Bei Kliniken mit einstelligen Fallzahlen könnten Fehlcodierungen schwerer ins Gewicht fallen und die Klinik fälschlicherweise als Stroke Unit mit Thrombektomiemöglichkeit klassifizieren.
Nicht alle der aufgeführten Klinikstandorte bieten rund um die Uhr Thrombektomien an. Nur bei überregionalen Stroke Units ist dies garantiert.

#### Weitere Limitationen 

In den Qualitätsberichten geben die Krankenhausstandorte bei weniger als 4 Fällen pro Jahr und pro Organisationseinheit aufgrund des Datenschutzes keine genaue Anzahl an. Wir rechnen dann optimistisch mit Fallzahl 3. In der Realität liegt die echte Fallzahl oft niedriger. 

Im Gegensatz zum [21-er-Datensatz](https://www.g-drg.de/datenlieferung-gem.-21-khentgg){target="_blank"} ist die Patient:innen-Fallhistorie aus den Daten der Qualitätsberichte des Jahres 2022 nicht ersichtlich und ICD- beziehungsweise OPS-Codes sind unabhängig voneinander angegeben. Bei einer Verlegung einer/eines Patient:in in eine andere Klinik kann es eventuell zu einer doppelten Zählung (insbesondere bei den ICD-Codes) kommen. 

Nicht alle Klinikstandorte erstellen Qualitätsberichte. Manche Krankenhäuser haben Fallzahlen der einzelnen Standorte im Qualitätsbericht des Hauptstandorts aufgelistet. Beispiel Charité in Berlin: Die Fallzahlen der Standorte Campus Virchow-Klinikum und Campus Benjamin Franklin stehen im Qualitätsbericht des Standorts Campus Mitte und werden nur im Namen der Organisationseinheit aufgeschlüsselt. In diesen Fällen bilden die Qualitätsberichte nicht ab, für welchen genauen Standort die Fallzahlen relevant sind. Dementsprechend richtet sich unsere Fahrzeitanalyse nach dem Standort, der die Fallzahlen in seinem Qualitätsbericht angibt. 

Wir können nur die als Codes angegeben Fälle auslesen. OPS-Codes für Schlaganfall-Komplexbehandlungen können nur von Standorten mit definierten Strukturmerkmalen angegeben werden. Alle anderen Kliniken rechnen ihre behandelten Schlaganfall-Fälle bislang über DRG-Fallpauschalen ab, die in diesem Datenreport nicht ausgewertet wurden. In einigen [telemedizinischen Netzwerken](https://link.springer.com/article/10.1007/s00115-021-01137-6){target="_blank"}  gibt es als Sonderfall zudem eine DRG-unabhängige Vergütung telemedizinischer Leistungen über Verträge mit den Krankenkassen. Für die Kliniken ohne die Strukturmerkmale für eine OPS-Codierung gibt es für uns keine Möglichkeit, eine Schlaganfall-Behandlung anhand eines OPS-Codes zu identifizieren.  

Kliniken, die über ein telemedizinisches Schlaganfall-Netzwerk in die Versorgung eingebunden sind und über einen Telekonsildienst beraten werden, können wir anhand der vorliegenden Datengrundlage nicht gesondert darstellen (siehe Definition eines schlaganfallversorgenden Klinikstandorts ohne „Stroke Unit“). Ob solche Klinken eine verbesserte Versorgungsqualität gegenüber Kliniken ohne telemedizinische Beratung aufweisen, ist Gegenstand einer [aktuell laufenden Studie](https://www.researchgate.net/publication/378344062_Impact_of_certified_stroke_care_A_nationwide_analysis_of_the_potential_to_improve_outcomes_PASCH){target="_blank"}. 

Die Berechnungen beruhen auf den Daten der Qualitätsberichte des Jahres 2022. In einzelnen Gebieten könnte es bereits neue Stroke Units geben oder Kliniken könnten geschlossen worden sein. 

#### Rückschlüsse auf die Behandlungsqualität 

Anhand unseres Datenreports können wir Standorte nur in die Kategorien „Stroke Unit“ und „andere schlaganfallversorgende Klinik“ einteilen. Dies lässt keine kategorischen Rückschlüsse auf die Behandlungsqualität zu: Auch innerhalb dieser Kategorien gibt es Qualitätsunterschiede, die Gegenstand [laufender Untersuchungen](https://www.researchgate.net/publication/378344062_Impact_of_certified_stroke_care_A_nationwide_analysis_of_the_potential_to_improve_outcomes_PASCH){target="_blank"} sind. Die möglichen Qualitätsunterschiede anhand von Strukturmerkmalen können wir anhand der Datenbasis in diesem Report nicht umfassend darstellen. 


#### Fahrzeitberechnung {#sec-methoden-fahrzeitberechnung} 

Die Daten zu den Fahrzeiten stammen von Tim Holthaus vom Lehrstuhl für Güterverkehr und Transportlogistik an der Universität Wuppertal. Die Fahrzeit bezieht sich auf eine Fahrt mit dem Pkw an einem Werktag zwischen sieben und elf Uhr. Grundlage für die Routenberechnung ist ein OpenStreetMap-Straßennetz, in dem für alle 100-Meter-Segmente die mittlere Geschwindigkeit aus Navigations-Daten aus dem Jahr 2017 verwendet wurden. Als Startpunkt der Routenberechnung wurde immer der Straßenknoten gewählt, der dem Mittelpunkt der Gitterzelle am nächsten liegt. Eine detaillierte Beschreibung der Methodik findet sich [hier](https://www.researchgate.net/publication/342211628_Evaluation_of_driven_speed_on_German_motorways_without_speed_limits_-_a_new_approach){target="_blank"}. 

Alle Gitterzellen innerhalb einer Gemeinde werden zusammengefasst und gemittelt. Dies geschieht gewichtet nach der Bevölkerung pro Gitterzelle. Die Bevölkerungsdaten stammen aus den [Zensus-Daten 2022](https://atlas.zensus2022.de/). Daraus ergibt sich für jede Gemeinde eine „mittlere Fahrzeit zur nächsten geeigneten Klinik“. Um die Fahrzeitveränderung zu bestimmen, wird dieser Vorgang zweimal durchgeführt. Einmal für alle Klinikstandorte mit Stroke Unit und einmal für alle Kliniken, die Schlaganfälle behandeln. Anschließend wird für jede Gemeinde die Differenz dieser zwei durchschnittlichen Fahrzeiten berechnet. 

##### Limitationen und Anmerkungen bezüglich der Fahrzeitberechnungen 

- Bei großen Kliniken mit mehreren Gebäuden kann die Adresse teilweise ungenau sein. Da die Adressen in derlei Fällen aber höchstens wenige hundert Meter voneinander entfernt liegen, spielt dies für die Fahrzeitenberechnung kaum eine Rolle. 
- Das zugrundeliegende OpenStreetMap-Straßennetz ist auf dem Stand von 2017. Straßen, die danach gebaut wurden, sind nicht berücksichtigt. 
- Die auf der Karte dargestellten Gemeindegrenzen und die Bevölkerungszahlen entsprechen dem Stand von 2022. Gebiete, für die auf der Karte keine Fahrzeit angegeben ist, sind gemeindefrei und unbewohnt. 
- In einigen Sonderfällen, wie bei Inseln, kann die Routenberechnung fehlerhaft sein, da hier Vereinfachungen bezüglich der Fährverbindungen getroffen wurden. Auch können fehlerhaft eingetragene Einbahnstraßen zu hohen Fahrzeiten in einzelnen Zellen führen. 
- Grenzregionen: Es werden nur Kliniken in Deutschland berücksichtigt. In Grenzregionen wird nicht berücksichtigt, dass Schlaganfälle auch in einen Klinikstandort in einem Nachbarland gebracht werden könnten. 
- Die Fahrzeit bezieht sich auf Fahrten nach der Straßenverkehrsordnung. Blaulicht-Fahrten von Rettungsdiensten könnten geringfügig schneller sein.

Mit Blick auf die Fahrzeitveränderung sind viele dieser Limitationen weniger relevant. Die Ungenauigkeiten in den absoluten Werten verschwinden zum größten Teil, da sie sowohl im Vorher- als auch im Nachher-Szenario eingerechnet wurden und bei der Differenzbildung wegfallen. 

### Datengrundlage und Code

Den Code für diesen Data Report stellen wir [hier]( `r file.path(imagepath, paste0(today()[Datumsprefix_files], "_"[Datumsprefix_files], file_name_code))` ){target="_blank"} zur Verfügung. Neben Standard R-Paketen wird ein eigenes Paket verwendet, das [hier](https://github.com/sciencemediacenter/SMChelpR){target="_blank"} bereitgestellt wird.

*In einer vorherigen Version des Reports wurde lediglich der Fachabteilungsschlüssel „2800“ (Neurologie) ausgelesen, um zu bestimmen, ob ein Klinikstandort eine Neurologie betreibt. In der aktuellen Version wird zusätzlich der Fachabteilungsschlüssel „2856“ (Neurologie/SP Schlaganfallpatienten (Stroke units)) herangezogen.*


### Ihre Ansprechpersonen in Redaktion und SMC Lab

Wenn Sie Fragen zu diesen Daten haben oder weitere Auswertungen erhalten wollen, kann das SMC Lab Auswertungen erzeugen.


*Redaktion*\
Philipp Jacobs, Redakteur für Medizin und Lebenswissenschaften\
Helena Salamun, Redakteurin für Medizin und Lebenswissenschaften
[redaktion\@sciencemediacenter.de](mailto:redaktion@sciencemediacenter.de){.email}

*Datenauswertung*\
Simon Essink\
Lars Koppers\
[lab\@sciencemediacenter.de](mailto:lab@sciencemediacenter.de){.email}


Telefon: +49 221 8888 25-0\
E-Mail Inhalt: [redaktion\@sciencemediacenter.de](mailto:redaktion@sciencemediacenter.de){.email}\
E-Mail Datenauswertung: [lab\@sciencemediacenter.de](mailto:lab@sciencemediacenter.de){.email}
:::
