library(rjson) library(shiny) library(bslib) library(leaflet) library(sf) library(htmltools) library(dplyr) library(tidyr) library(purrr) library(ggplot2) library(ggthemes) library(stringr) library(plotly) library(htmlwidgets) #große JSON Datei lesen crime_json <- fromJSON(file="data.json") get_bezirk_by_stadtteil <- function(name) { parents <- names(crime_json)[sapply(crime_json, function(item) name %in% names(item))] if (length(parents) == 0) return(NULL) parents } #Wichtige Informationen aus passender Ebene/Row von der JSON Datei holen, um sie für das tibble zu nutzen #trimws steht für trim whitespace, sorgt für sauberen string beim Jahr #map_df steht für map dataframe #aufgekärte Fälle sind auch im tibble drin, hätten wir also bei mehr Zeit oder für ,ehr Funktionen auch direkt nutzen können map_data_to_table <- function(bezirk, stadtteil, year) { year <- as.character(trimws(year)) map_df(names(crime_json[[bezirk]][[stadtteil]]), function(crime) { row <- crime_json[[bezirk]][[stadtteil]][[crime]][[year]] tibble( Name = crime, `Erfasste Fälle` = as.integer(row[["Erfasste Fälle"]]), `Aufgeklärte Fälle` = as.integer(row[["Aufgeklärte Fälle"]]), `Aufklärung relativ` = paste(row[["Aufklärung relativ"]], "%", sep=""), ) }) } #Vorbereitung für Balkendiagram top3 Straftaten #Sortieren und Beschränken auf die Ränge 2, 3 und 4 #Sortieren: Absteigend nach "Erfasste Fälle". Der höchste Wert ist nun in Zeile 1. #mit slice sind explizit die Ränge 2, 3 und 4 gemeint map_data_to_top3_plot <- function(bezirk, stadtteil, year) { year <- as.character(trimws(year)) req(bezirk) req(stadtteil) req(year) komplettes_tibble <- map_df(names(crime_json[[bezirk]][[stadtteil]]), function(crime) { row <- crime_json[[bezirk]][[stadtteil]][[crime]][[year]] tibble( Name = str_wrap(crime, width = 25), Erfasst = as.integer(row[["Erfasste Fälle"]]), ) }) top_3_tibble <- komplettes_tibble %>% arrange(desc(Erfasst)) %>% slice(2:4) return(top_3_tibble) } #Vorbereitung für Balkendiagramm auf Vergleichs-tab #Location beinhaltet Stadtteile und Bezirke, um alle Auswahlmöglichkeiten in einem drop down zu haben #die App weiß, wann es sich um einen Bezirk handelt, wenn die ersten 7 Stellen mit dem Wort "Bezirk" übereinstimmen? #Erfasste Fälle als Zahl (integer) angeben, die Straftaten (crimes) mit Zeilenumbruch bei bestimmter Breite angeben #Sortierung nach Anzhal der erfassten Fälle absteigend map_data_to_plot <- function(locations, crimes, year) { year <- as.character(trimws(year)) req(locations) req(crimes) req(year) return(map_df(locations, function(loc) { bezirk <- "" stadtteil <- "" if (substring(loc, 1, 6) == "Bezirk") { bezirk <- substring(loc, 8, nchar(loc)) stadtteil <- loc } else { bezirk <- get_bezirk_by_stadtteil(loc) stadtteil <- loc } komplettes_tibble <- map_df(crimes, function(crime) { row <- crime_json[[bezirk]][[stadtteil]][[crime]][[year]] tibble( Name = str_wrap(crime, width = 25), Erfasst = as.integer(row[["Erfasste Fälle"]]), Location = loc ) }) }) %>% arrange(desc(Erfasst)) ) } #lass mal hier statt delikt crime nehmen oder eben die anderen crimes delikt, oder gibt es einen Grund dass es anders heißt/auf deutsch ist? #Mit dieser Funktion entnehmen wir die gewünschten Einträge, Straftat, Jahr, Erfasste Fälle direkt aus der JSON Datei und erhalten so unseren dataframe, den wir wofür nutzen können? #sicherer Zugriff (verhindert Fehler bei fehlenden Einträgen) get_intensity_df <- function(crime_json, delikt, jahr = "2024", feld = "Erfasste Fälle") { do.call(rbind, lapply(names(crime_json), function(bezirk) { stadtteile <- crime_json[[bezirk]] data.frame( bezirk = bezirk, stadtteil = names(stadtteile), intensity = sapply(stadtteile, function(st) { val <- st[[delikt]][[jahr]][[feld]] if (is.null(val)) NA else val }), row.names = NULL ) })) } #GeoJson für Bezirke #st_transform sorgt für die Umwandlung der Geo-Daten in das Standard-Koordinatensystem WGS 84, csr bedeutet Koordinatenreferenzsystem #mit paste("bez_") bilden wir die jeweiligen Präfixe für Stadtteil und Bezirk, damit aufgrund dieses Merkmals die app die beiden Typen voneinander unterscheiden kann geo_bezirke <- st_read("geobezirke-parsed.json") geo_bezirke <- st_transform(geo_bezirke, crs = 4326) geo_bezirke$leaflet_id <- paste("bez_", geo_bezirke$bezirk, sep="") #GeoJson für Stadtteile geo_stadtteile <- st_read("geostadtteile-parsed.json") geo_stadtteile <- st_transform(geo_stadtteile, crs = 4326) geo_stadtteile$leaflet_id <- paste("std_", geo_stadtteile$stadtteil, sep="") bezirke <- sort(names(crime_json)) list_of_crimes <- sort(c(unique(unlist( lapply(crime_json, function(a) { unlist( lapply(a, function(b) { names(b) }), use.names = FALSE ) }), use.names = FALSE )), "")) #map(names) wendet names() auf jedes Element der ersten Ebene, wie Bezirke ("A", "B", "C") an. #Ergebnis: Eine Liste von Vektoren (z.B. list(c("aa1", "aa2"), c("bb1", "bb2"), c("cc1"))), hier: Stadtteile #unlist() vereint alle diese Vektoren zu einem einzigen Vektor. #Ergebnis: c("aa1", "aa2", "bb1", "bb2", "cc1") #unique(): auf Nummer sicher gehen, dass die Stadtteile alle eindeutig sind. auswahlmöglichkeiten <- crime_json %>% map(names) %>% unlist() %>% unique() %>% sort() %>% setdiff("Alle")