|
| 1 | +^{:kindly/hide-code true |
| 2 | + :clay {:title "Pedestrian counts in cities" |
| 3 | + :external-requirements [] ;; confirm - this is how to take pre-rendered .qmd as per: https://clojurecivitas.github.io/scicloj/clay/skip_if_unchanged_example.html ? |
| 4 | + :quarto {:author [:pez |
| 5 | + :antonzhyliuk |
| 6 | + :tomas81508 |
| 7 | + :chrysophylax |
| 8 | + :dts |
| 9 | + :daslu] |
| 10 | + :type :post |
| 11 | + :date "2026-05-20" |
| 12 | + :category :gis |
| 13 | + :tags [:gis]} |
| 14 | + :draft true}} |
| 15 | +(ns gis.pedestrian-counts) |
| 16 | + |
| 17 | + |
| 18 | + |
| 19 | +(ns gis.pedestrian-counts |
| 20 | + (:require [tablecloth.api :as tc] |
| 21 | + [tablecloth.column.api :as tcc] |
| 22 | + [scicloj.plotje.api :as pj] |
| 23 | + [tech.v3.datatype.datetime :as datetime] |
| 24 | + [scicloj.kindly.v4.kind :as kind] |
| 25 | + [clojure.string :as str])) |
| 26 | + |
| 27 | + |
| 28 | +(def data-path |
| 29 | + "data/kaggle/nordcauc-urban-mobility-intelligence/pedestrian_flow_counters.csv.gz") |
| 30 | + |
| 31 | + |
| 32 | + |
| 33 | +(def ped-data |
| 34 | + (-> data-path |
| 35 | + (tc/dataset {:key-fn keyword}))) |
| 36 | + |
| 37 | + |
| 38 | +ped-data |
| 39 | + |
| 40 | +(type ped-data) |
| 41 | + |
| 42 | +(map? ped-data) |
| 43 | + |
| 44 | +(-> ped-data |
| 45 | + (tc/select-rows (fn [row] |
| 46 | + (-> row :counter_id (= "PD-ST-0001")))) |
| 47 | + (tc/select-columns [:hour :total_count_hourly]) |
| 48 | + pj/pose) |
| 49 | + |
| 50 | + |
| 51 | +(-> ped-data |
| 52 | + (tc/select-rows (fn [row] |
| 53 | + (-> row :counter_id (= "PD-ST-0001")))) |
| 54 | + (tc/group-by [:hour]) |
| 55 | + (tc/aggregate {:avg-count (fn [ds] |
| 56 | + (-> ds |
| 57 | + :total_count_hourly |
| 58 | + tcc/mean))}) |
| 59 | + pj/pose |
| 60 | + pj/lay-line |
| 61 | + pj/lay-point) |
| 62 | + |
| 63 | + |
| 64 | + |
| 65 | + |
| 66 | +(-> ped-data |
| 67 | + (tc/select-rows (fn [row] |
| 68 | + (-> row :counter_id (= "PD-ST-0001")))) |
| 69 | + (tc/group-by [:season :hour]) |
| 70 | + (tc/aggregate {:avg-count (fn [ds] |
| 71 | + (-> ds |
| 72 | + :total_count_hourly |
| 73 | + tcc/mean))}) |
| 74 | + (pj/pose :hour :avg-count {:color :season}) |
| 75 | + pj/lay-line) |
| 76 | + |
| 77 | + |
| 78 | +(-> ped-data |
| 79 | + (tc/group-by [:counter_id] {:result-type :as-seq}) |
| 80 | + (->> (sort-by (fn [station-counts] |
| 81 | + (-> station-counts |
| 82 | + (tc/rows :as-maps) |
| 83 | + first |
| 84 | + :location_type))) |
| 85 | + (map (fn [station-counts] |
| 86 | + (-> station-counts |
| 87 | + (tc/group-by [:season :hour]) |
| 88 | + (tc/aggregate {:avg-count (fn [ds] |
| 89 | + (-> ds |
| 90 | + :total_count_hourly |
| 91 | + tcc/mean))}) |
| 92 | + (pj/pose :hour :avg-count {:color :season}) |
| 93 | + pj/lay-line |
| 94 | + (pj/options {:title (-> station-counts |
| 95 | + (tc/rows :as-maps) |
| 96 | + first |
| 97 | + ((juxt :city :district :location_type)) |
| 98 | + (->> (str/join " ")))})))))) |
| 99 | + |
| 100 | + |
| 101 | + |
| 102 | +(-> ped-data |
| 103 | + (tc/group-by [:counter_id] {:result-type :as-seq}) |
| 104 | + (->> (sort-by (fn [station-counts] |
| 105 | + (-> station-counts |
| 106 | + (tc/rows :as-maps) |
| 107 | + first |
| 108 | + :location_type))) |
| 109 | + (map (fn [station-counts] |
| 110 | + (let [first-row (-> station-counts |
| 111 | + (tc/rows :as-maps) |
| 112 | + first) |
| 113 | + center [(:latitude first-row) |
| 114 | + (:longitude first-row)]] |
| 115 | + (kind/fragment |
| 116 | + [(kind/reagent |
| 117 | + ['(fn [input-center] |
| 118 | + [:div {:style {:height "200px"} |
| 119 | + :ref (fn [el] |
| 120 | + (let [m (-> js/L |
| 121 | + (.map el) |
| 122 | + (.setView (clj->js |
| 123 | + input-center) |
| 124 | + 14))] |
| 125 | + (-> js/L |
| 126 | + .-tileLayer |
| 127 | + (.provider "Stadia.AlidadeSmooth") |
| 128 | + (.addTo m)) |
| 129 | + (-> js/L |
| 130 | + (.marker (clj->js input-center)) |
| 131 | + (.addTo m))))}]) |
| 132 | + center] |
| 133 | + ;; Note we need to mention the dependency: |
| 134 | + {:html/deps [:leaflet]}) |
| 135 | + (-> station-counts |
| 136 | + (tc/group-by [:season :hour]) |
| 137 | + (tc/aggregate {:avg-count (fn [ds] |
| 138 | + (-> ds |
| 139 | + :total_count_hourly |
| 140 | + tcc/mean))}) |
| 141 | + (pj/pose :hour :avg-count {:color :season}) |
| 142 | + pj/lay-line |
| 143 | + (pj/options {:title (->> first-row |
| 144 | + ((juxt :city :district :location_type)) |
| 145 | + (str/join " "))}))])))) |
| 146 | + kind/fragment)) |
| 147 | + |
| 148 | + |
| 149 | + |
| 150 | + |
| 151 | + |
| 152 | + |
| 153 | + |
| 154 | + |
| 155 | + |
| 156 | + |
| 157 | + |
| 158 | + |
0 commit comments