Skip to content

Commit

Permalink
Merge pull request #113 from Hong-Kong-Districts-Info/feat/21-data-up…
Browse files Browse the repository at this point in the history
…date

Feat: Add 2020 and 2021 collision data
  • Loading branch information
KHwong12 authored Dec 25, 2023
2 parents cf03eda + 8d509d8 commit ba256e7
Show file tree
Hide file tree
Showing 12 changed files with 181 additions and 173 deletions.
Binary file not shown.
Binary file modified inst/app/data/hk_casualties.fst
Binary file not shown.
Binary file not shown.
Binary file modified inst/app/data/hk_vehicles.fst
Binary file not shown.
6 changes: 3 additions & 3 deletions inst/app/global.R
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ i18n$use_js()
# Data import -------------------------------------------------------------

## Take data from {hkdatasets}
hk_accidents <- fst::read_fst("./data/hk_accidents.fst")
hk_collisions <- fst::read_fst("./data/hk_collisions.fst")
hk_vehicles <- fst::read_fst("./data/hk_vehicles.fst")
hk_casualties <- fst::read_fst("./data/hk_casualties.fst")

Expand All @@ -67,7 +67,7 @@ hotzone_streets = read_sf("./data/hotzone_streets.gpkg")
terminology = read.csv("./data/terminology.csv")

## Manipulated data, generated from `modules/manipulate_data.R`
hk_accidents_valid_sf = read_sf("./data/data-manipulated/hk_accidents_valid_sf.gpkg")
hk_collisions_valid_sf = read_sf("./data/data-manipulated/hk_collisions_valid_sf.gpkg")
hotzone_out_df = fst::read_fst("./data/data-manipulated/hotzone_out_df.fst")

# interactive thematic map mode option ------------------------------------
Expand All @@ -86,7 +86,7 @@ DISTRICT_FULL_NAME = hkdatasets::hkdistrict_summary[["District_EN"]]
# Color scheme ------------------------------------------------------------

SEVERITY_COLOR = c(Fatal = "#FF4039", Serious = "#FFB43F", Slight = "#FFE91D")
CATEGORY_COLOR = setNames(as.list(c("#232323", "#232323", "#232323")), c("accidents", "casualties", "vehicles"))
CATEGORY_COLOR = setNames(as.list(c("#232323", "#232323", "#232323")), c("collisions", "casualties", "vehicles"))

# Fill color palette according to the severity of the accident
fill_palette = leaflet::colorFactor(palette = c("#FF4039", "#FFB43F", "#FFE91D"), domain = c("Fatal", "Serious", "Slight"))
Expand Down
53 changes: 27 additions & 26 deletions inst/app/modules/district_dsb.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,46 @@
# Translation terms

COLLISION_SEVERITY_TRANSLATE = data.frame(
Severity = c("Slight", "Serious", "Fatal"),
Severity_chi = c("輕微", "嚴重", "致命")
severity = c("Slight", "Serious", "Fatal"),
severity_chi = c("輕微", "嚴重", "致命")
)

COLLISION_TYPE_TRANSLATE = data.frame(
Collision_Type = c(
collision_type_with_cycle = c(
"Vehicle collision with Vehicle", "Vehicle collision with Pedestrian", "Vehicle collision with Pedal Cycle",
"Vehicle collision with Object", "Vehicle collision with Nothing", "Pedal Cycle collision with Pedestrian",
"Pedal Cycle collision with Pedal Cycle", "Pedal Cycle collision with Object", "Pedal Cycle collision with Nothing"
"Pedal Cycle collision with Pedal Cycle", "Pedal Cycle collision with Object", "Pedal Cycle collision with Nothing",
"Unknown vehicle collision type"
),
Collision_Type_chi = c(
collision_type_with_cycle_chi = c(
"車撞車", "車撞行人", "車撞單車",
"車撞物", "車輛沒有碰撞", "單車撞行人",
"單車撞單車", "單車撞物", "單車沒有碰撞"
"單車撞單車", "單車撞物", "單車沒有碰撞",
"類別不明"
)
)

VEHICLE_CLASS_TRANSLATE = data.frame(
Vehicle_Class = c(
vehicle_class = c(
"Private car", "Public franchised bus", "Taxi", "Motorcycle", "Light goods vehicle",
"Bicycle", "Heavy goods vehicle", "Medium goods vehicle", "Tram", "Public light bus",
"Others (incl. unknown)", "Public non-franchised bus", "Light rail vehicle"),
Vehicle_Class_chi = c(
vehicle_class_chi = c(
"私家車", "公共專營巴士", "的士", "電單車", "輕型貨車",
"單車", "重型貨車", "中型貨車", "電車", "公共小巴",
"其他(包括類別不詳車輛)", "公共非專營巴士", "輕鐵車輛"
)
)

# Unique Main_vehicle values extracted from hk_vehicles
# TODO: Unify the capitalisation rules
# Unique vehicle movement values extracted from hk_vehicles
VEHICLE_MOVEMENT_TRANSLATE = data.frame(
Main_vehicle = c(
vehicle_movement = c(
"Going straight ahead (with priority)", "Changing lanes or merging", "Overtaking on off-side",
"Overtaking on near-side", "Going Straight Ahead (against priority)", "Making right turn", "Making left turn",
"Making U turn", "Slowing or stopping", "Stopped in traffic", "Starting in traffic", "Leaving parking place",
"Parked", "Reversing", "Driverless moving vehicle", "Ran off road", "Other", "Unknown"
),
Main_vehicle_chi = c(
vehicle_movement_chi = c(
"向前駛 (優先)", "轉換行車線", "從外線超車",
"從內線超車", "向前駛(無優先)", "右轉", "左轉",
"掉頭", "慢駛或停車", "因前路受阻而停車", "跟隨前面交通開車", "駛離泊車位",
Expand All @@ -50,21 +51,21 @@ VEHICLE_MOVEMENT_TRANSLATE = data.frame(
)

PED_ACTION_TRANSLATE = data.frame(
Ped_Action = c(
ped_action = c(
"Walking - back to traffic", "Walking - facing traffic", "Standing", "Boarding vehicle",
"Alighting from vehicle", "Falling or jumping from vehicle", "Working at a vehicle", "Other working",
"Playing", "Crossing from near-side", "Crossing from off-side", "Not known"
),
Ped_Action_chi = c(
ped_action_chi = c(
"步行 ─ 背向車流", "步行 ─ 面向車流", "站立", "正在登車",
"正在下車", "從車上跌下或跳下", "在修車中", "其他工作",
"在玩耍中", "從車左邊橫過馬路", "從車右邊橫過馬路", "資料不詳"
)
)

ROAD_HIERARCHY_TRANSLATE = data.frame(
Road_Hierarchy = c("Expressway", "Main Road", "Secondary Road", "Other Minor Road", "Cycle Track/Others"),
Road_Hierarchy_chi = c("快速公路", "主要道路", "次要道路(內街/支路)", "小路(鄉村道路/行人徑)", "單車徑/其他")
road_hierarchy = c("Expressway", "Main Road", "Secondary Road", "Other Minor Road", "Cycle Track/Others"),
road_hierarchy_chi = c("快速公路", "主要道路", "次要道路(內街/支路)", "小路(鄉村道路/行人徑)", "單車徑/其他")
)


Expand Down Expand Up @@ -93,31 +94,31 @@ output$ksi_filter_ui = renderUI({
})


# Return filtered hk_accidents dataframe according to users' selected inputs
ddsb_filtered_hk_accidents = reactive({
# Return filtered hk_collisions dataframe according to users' selected inputs
ddsb_filtered_hk_collisions = reactive({
# filter by users' selected district
# FIXME: Temp workaround to fix non-initialised value when district filter renders in server side
ddsb_district_filter = if (is.null(input$ddsb_district_filter)) "CW" else input$ddsb_district_filter
hk_accidents_filtered = filter(hk_accidents, District_Council_District == ddsb_district_filter)
hk_collisions_filtered = filter(hk_collisions, district == ddsb_district_filter)

# filter by users' selected time range
hk_accidents_filtered = filter(hk_accidents_filtered, Year >= input$ddsb_year_filter[1] & Year <= input$ddsb_year_filter[2])
hk_collisions_filtered = filter(hk_collisions_filtered, year >= input$ddsb_year_filter[1] & year <= input$ddsb_year_filter[2])

# remove slightly injured collisions if user select "KSI only" option
# FIXME: Temp workaround to fix non-initialised value when KSI filter renders in server side
ddsb_ksi_filter = if (is.null(input$ddsb_ksi_filter)) "all" else input$ddsb_ksi_filter

if (ddsb_ksi_filter == "ksi_only") {
hk_accidents_filtered = filter(hk_accidents_filtered, Severity != "Slight")
hk_collisions_filtered = filter(hk_collisions_filtered, severity != "Slight")
}

# Show only collisions with valid lng/lat
hk_accidents_filtered = hk_accidents_filtered %>%
filter(!is.na(Grid_E) & !is.na(Grid_N)) %>%
st_as_sf(coords = c("Grid_E", "Grid_N"), crs = 2326, remove = FALSE)
hk_collisions_filtered = hk_collisions_filtered %>%
filter(!is.na(easting) & !is.na(northing)) %>%
st_as_sf(coords = c("easting", "northing"), crs = 2326, remove = FALSE)

print(nrow(hk_accidents_filtered))
print(paste0("Number of records filtered in districh dashboard: ", nrow(hk_collisions_filtered)))

hk_accidents_filtered
hk_collisions_filtered

})
62 changes: 31 additions & 31 deletions inst/app/modules/district_dsb_all.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,29 @@
ddsb_filtered_hk_casualties = reactive({

# vector of Serial No. in selected range
serial_no_filtered = unique(ddsb_filtered_hk_accidents()[["Serial_No_"]])
serial_no_filtered = unique(ddsb_filtered_hk_collisions()[["serial_no"]])

filter(hk_casualties, Serial_No_ %in% serial_no_filtered)
filter(hk_casualties, serial_no %in% serial_no_filtered)
})

# filtered hk_vehicles
ddsb_filtered_hk_vehicles = reactive({

# vector of Serial No. in selected range
serial_no_filtered = unique(ddsb_filtered_hk_accidents()[["Serial_No_"]])
serial_no_filtered = unique(ddsb_filtered_hk_collisions()[["serial_no"]])

filter(hk_vehicles, Serial_No_ %in% serial_no_filtered)
filter(hk_vehicles, serial_no %in% serial_no_filtered)
})

all_grid_count = reactive({
count_collisions_in_grid(ddsb_filtered_hk_accidents())
count_collisions_in_grid(ddsb_filtered_hk_collisions())
})


# Outputs ----------------------------------

output$box_all_total_collision = renderInfoBox({
n_collision = nrow(ddsb_filtered_hk_accidents())
n_collision = nrow(ddsb_filtered_hk_collisions())

infoBox(
title = "",
Expand All @@ -51,7 +51,7 @@ output$box_all_total_casualty = renderInfoBox({
})

output$box_all_serious_stat = renderInfoBox({
n_serious = nrow(filter(ddsb_filtered_hk_casualties(), Degree_of_Injury == "Seriously Injured"))
n_serious = nrow(filter(ddsb_filtered_hk_casualties(), injury_degree == "Seriously Injured"))
serious_per = round(n_serious / nrow(ddsb_filtered_hk_casualties()) * 100, digits = 1)

infoBox(
Expand All @@ -64,7 +64,7 @@ output$box_all_serious_stat = renderInfoBox({
})

output$box_all_fatal_stat = renderInfoBox({
n_fatal = nrow(filter(ddsb_filtered_hk_casualties(), Degree_of_Injury == "Killed"))
n_fatal = nrow(filter(ddsb_filtered_hk_casualties(), injury_degree == "Killed"))
fatal_per = round(n_fatal / nrow(ddsb_filtered_hk_casualties()) * 100, digits = 1)

infoBox(
Expand Down Expand Up @@ -101,13 +101,13 @@ output$ddsb_all_collision_heatmap = renderTmap({
output$ddsb_all_ksi_plot = renderPlotly({

# count by severity
plot_data = count(ddsb_filtered_hk_accidents(), Severity, name = "count", na.rm = TRUE) %>%
left_join(COLLISION_SEVERITY_TRANSLATE, by = "Severity") %>%
plot_data = count(ddsb_filtered_hk_collisions(), severity, name = "count", na.rm = TRUE) %>%
left_join(COLLISION_SEVERITY_TRANSLATE, by = "severity") %>%
# Force order of the categorical axis
# Factor in reversed order since last element in factor is plotted on top in ggplot
mutate(Severity_text = factor(paste0(Severity_chi, "\n", Severity), c("致命\nFatal", "嚴重\nSerious", "輕微\nSlight")))
mutate(severity_text = factor(paste0(severity_chi, "\n", severity), c("致命\nFatal", "嚴重\nSerious", "輕微\nSlight")))

plot_by_severity = ggplot(plot_data, aes(x = Severity_text, y = count, fill = Severity)) +
plot_by_severity = ggplot(plot_data, aes(x = severity_text, y = count, fill = severity)) +
geom_bar(stat = "identity") +
coord_flip() +
scale_fill_manual(values = SEVERITY_COLOR) +
Expand All @@ -125,9 +125,9 @@ output$ddsb_all_ksi_plot = renderPlotly({
# Collision by year plot
output$ddsb_all_year_plot = renderPlotly({

plot_data = count(ddsb_filtered_hk_accidents(), Year, name = "count", na.rm = TRUE)
plot_data = count(ddsb_filtered_hk_collisions(), year, name = "count", na.rm = TRUE)

collision_year_trend_plot = ggplot(plot_data, aes(x = Year, y = count)) +
collision_year_trend_plot = ggplot(plot_data, aes(x = year, y = count)) +
geom_line() +
theme_minimal() +
theme(
Expand All @@ -144,15 +144,15 @@ output$ddsb_all_year_plot = renderPlotly({
output$ddsb_all_collision_type_plot = renderPlotly({

# count by pedestrian Action
plot_data = ddsb_filtered_hk_accidents() %>%
count(Type_of_Collision_with_cycle, name = "count") %>%
left_join(COLLISION_TYPE_TRANSLATE, by = c("Type_of_Collision_with_cycle" = "Collision_Type")) %>%
plot_data = ddsb_filtered_hk_collisions() %>%
count(collision_type_with_cycle, name = "count") %>%
left_join(COLLISION_TYPE_TRANSLATE, by = c("collision_type_with_cycle" = "collision_type_with_cycle")) %>%
# Merge both en and zh values, then reorder vehicle class in descending order
mutate(Collision_Type_order = reorder(paste0(Collision_Type_chi, "\n", Type_of_Collision_with_cycle), count))
mutate(collision_type_with_cycle_order = reorder(paste0(collision_type_with_cycle_chi, "\n", collision_type_with_cycle), count))


plot_by_collision_type = ggplot(plot_data, aes(x = Collision_Type_order, y = count)) +
geom_bar(stat = "identity", fill = CATEGORY_COLOR$accidents) +
plot_by_collision_type = ggplot(plot_data, aes(x = collision_type_with_cycle_order, y = count)) +
geom_bar(stat = "identity", fill = CATEGORY_COLOR$collisions) +
coord_flip() +
theme_minimal() +
theme(
Expand All @@ -170,12 +170,12 @@ output$ddsb_all_collision_type_plot = renderPlotly({
output$ddsb_all_vehicle_class_plot = renderPlotly({

# count by Vehicle_Class
plot_data = count(ddsb_filtered_hk_vehicles(), Vehicle_Class, name = "count", na.rm = TRUE) %>%
left_join(VEHICLE_CLASS_TRANSLATE, by = c("Vehicle_Class" = "Vehicle_Class")) %>%
plot_data = count(ddsb_filtered_hk_vehicles(), vehicle_class, name = "count", na.rm = TRUE) %>%
left_join(VEHICLE_CLASS_TRANSLATE, by = c("vehicle_class" = "vehicle_class")) %>%
# Merge both en and zh values, then reorder vehicle class in descending order
mutate(Vehicle_Class_order = reorder(paste0(Vehicle_Class_chi, "\n", Vehicle_Class), count))
mutate(vehicle_class_order = reorder(paste0(vehicle_class_chi, "\n", vehicle_class), count))

plot_by_vehicle_class = ggplot(plot_data, aes(x = Vehicle_Class_order, y = count)) +
plot_by_vehicle_class = ggplot(plot_data, aes(x = vehicle_class_order, y = count)) +
geom_bar(stat = "identity", fill = CATEGORY_COLOR$vehicles) +
coord_flip() +
theme_minimal() +
Expand All @@ -195,16 +195,16 @@ output$ddsb_all_vehicle_class_plot = renderPlotly({
output$ddsb_all_road_hierarchy_plot = renderPlotly({

# count by pedestrian Action
plot_data = ddsb_filtered_hk_accidents() %>%
filter(!is.na(Road_Hierarchy)) %>%
count(Road_Hierarchy, name = "count") %>%
left_join(ROAD_HIERARCHY_TRANSLATE, by = c("Road_Hierarchy" = "Road_Hierarchy")) %>%
plot_data = ddsb_filtered_hk_collisions() %>%
filter(!is.na(road_hierarchy)) %>%
count(road_hierarchy, name = "count") %>%
left_join(ROAD_HIERARCHY_TRANSLATE, by = c("road_hierarchy" = "road_hierarchy")) %>%
# Merge both en and zh values, then reorder vehicle class in descending order
mutate(Road_Hierarchy_order = reorder(paste0(Road_Hierarchy_chi, "\n", Road_Hierarchy), count))
mutate(road_hierarchy_order = reorder(paste0(road_hierarchy_chi, "\n", road_hierarchy), count))


plot_by_road_hierarchy = ggplot(plot_data, aes(x = Road_Hierarchy_order, y = count)) +
geom_bar(stat = "identity", fill = CATEGORY_COLOR$accidents) +
plot_by_road_hierarchy = ggplot(plot_data, aes(x = road_hierarchy_order, y = count)) +
geom_bar(stat = "identity", fill = CATEGORY_COLOR$collisions) +
coord_flip() +
theme_minimal() +
theme(
Expand Down
Loading

0 comments on commit ba256e7

Please sign in to comment.