Analisi Covid-19 Italia
{:deps {org.clojure/clojure {:mvn/version "1.10.1"} org.clojure/data.csv {:mvn/version "1.0.0"} cheshire/cheshire {:mvn/version "5.10.0"} metosin/jsonista {:mvn/version "0.2.7"}}}Extensible Data Notation
curl https://raw.githubusercontent.com/pcm-dpc/COVID-19/master/dati-json/dpc-covid19-ita-andamento-nazionale.json > data.jsoncurl https://raw.githubusercontent.com/pcm-dpc/COVID-19/master/dati-json/dpc-covid19-ita-regioni.json > data_region.jsoncurl https://raw.githubusercontent.com/pcm-dpc/COVID-19/master/dati-json/dpc-covid19-ita-province.json > data_province.jsonRetrieve data
3.4s
date0.9s
italy-population.csv
2.18 KBDownload(require [cheshire.core :as json])(def national-data (json/parse-string (slurp "/data.json") true))(reverse national-data)_(keys (first national-data))3.3s
(def selected-keys [:totale_casi :dimessi_guariti :deceduti :tamponi :tamponi_test_molecolare :totale_ospedalizzati :terapia_intensiva :ingressi_terapia_intensiva :data])(def clean-data (distinct (map (select-keys % selected-keys) national-data)))(def a (take-last 5 clean-data))(defn calculate-delta [coll] (map (fn [a b] (into {} (map (fn [[k1 v1] [_ v2]] (case k1 :data [k1 v1] [k1 (when (and v2 v1) (- v2 v1))])) a b))) coll (rest coll)))(defn moving-average [n coll] (let [[n1 n2] (split-with nil? coll)] (concat n1 (when-let [[x & xs] (seq n2)] (map (/ % n) (reductions + (* n x) (map - xs (concat (repeat n x) xs))))))))(def incremental-data (calculate-delta clean-data))(defn plot [input plot-spec opts] (let [incremental-data (calculate-delta input)] {:nextjournal/viewer :plotly} {:data (map (fn [{:keys [key color incremental? legend]}] {:name legend :mode "lines" :line {:color color} :x (map (comp (apply str %) (take 10 %) :data) input) :y (cond->> (map key (if incremental? incremental-data input)) (:average opts) (moving-average (:average opts)))}) plot-spec) :layout {:margin {:l 80 :b 50 :r 50 :t 50} :xaxis {:autotick true :automargin true :showticklabels true} :yaxis {:automargin true} }}))(def c (last clean-data))(def d (last incremental-data))(clojure.pprint/pprint {:nuovi-casi (:totale_casi d) :tamponi (:tamponi d) :ultimo-dato (:data c) :tamponi-pcr (:tamponi_test_molecolare d) :dimessi-guariti (:dimessi_guariti d) :nuovi-deceduti (:deceduti d) :delta-terapia-intensiva (:terapia_intensiva d) :nuovi-ingressi-terapia-intensiva (:ingressi_terapia_intensiva c)})0.8s
(require [clojure.data.csv :as csv] [clojure.set :as set])(def pop (->> (csv/read-csv (slurp italy-population.csv)) (drop 1) (map (fn [[k n]] [k (Integer/parseInt n)])) (into {}) ))(def keys-to-rename {"Valle d'Aosta / Vallée d'Aoste" "Valle d'Aosta" "Bolzano / Bozen" "P.A. Bolzano" "Trento" "P.A. Trento"})(def pop-100k (into {} (map (fn [[k v]] [k (float (/ v 100000))]) (set/rename-keys pop keys-to-rename))))(sort-by second > pop-100k)0.6s
Nuovi positivi
Dati grezzi
(def positive-plot [{:key :totale_casi :color "orchid" :legend "Nuovi positivi" :incremental? true} {:key :deceduti :color "tomato" :legend "Deceduti" :incremental? true} {:key :dimessi_guariti :color "limegreen" :legend "Guariti" :incremental? true}])(plot clean-data positive-plot {})_(map (comp (apply str %) (take 10 %) :data) clean-data)0.7s
Media mobile di 7-giorni
(plot clean-data positive-plot {:average 7})0.7s
Test e nuovi positivi
Dati grezzi
(def tests-plot [{:key :totale_casi :color "orchid" :legend "Nuovi positivi" :incremental? true} {:key (fn [r] (or (:tamponi_test_molecolare r) (:tamponi r))) :color "darkcyan" :legend "Tamponi" :incremental? true}])(plot clean-data tests-plot {})0.5s
Media mobile di 7 giorni
(plot clean-data tests-plot {:average 7})0.5s
Ricoveri e TI (dato attuale)
(def hospital-plot [{:key :totale_ospedalizzati :color "red" :legend "Ricoverati" :incremental? false} {:key :terapia_intensiva :color "orange" :legend "Terapia Intensiva" :incremental? false}])(plot clean-data hospital-plot {})0.6s
Ingressi giornalieri TI
(def ti-plot [{:key :ingressi_terapia_intensiva :color "red" :legend "Ingressi TI" :incremental? false}])(plot clean-data ti-plot {:average 7 :last 60})0.8s
Dati regionali (normalizzati, per 100k abitanti)
(def regional-data (json/parse-string (slurp "/data_region.json") true))regional-data8.3s
(defn region-data [region-name] (->> regional-data (filter (= (:denominazione_regione %) region-name)) (map (select-keys % selected-keys)) distinct))(def regions {"Lombardia" "black" "Emilia-Romagna" "darkgreen" "Veneto" "deepskyblue" "Sicilia" "gold" "Piemonte" "brown" "Marche" "orange" "Toscana" "chocolate" "Lazio" "red" "Liguria" "grey" "Campania" "skyblue" "Puglia" "orchid"})(def data-by-region (->> (keys regions) (map (fn [r] [r (region-data r)])) (into {})))(defn y [region-name data {:keys [measure incremental? by-100k? average last]}] (let [values (map measure (if incremental? (calculate-delta data) data)) result (cond->> values by-100k? (map (fn [x] (when x (/ x (get pop-100k region-name))))) average (moving-average average) last (take-last last))] result))(defn plot-regional-data [{:keys [last] :as opts}] {:nextjournal/viewer "plotly"} {:data (mapv (fn [[region-name color]] (let [data (get data-by-region region-name)] {:name region-name :mode "lines" :line {:color color} :x (cond->> (map (comp (apply str %) (take 10 %) :data) data) last (take-last last)) :y (y region-name data opts)})) regions) :layout {:xaxis {:autotick true :automargin true}}} )0.1s
Nuovi casi
(plot-regional-data {:measure :totale_casi :by-100k? true :incremental? true :average 7 :last 90})1.1s
Tamponi
(plot-regional-data {:measure (fn [r] (or (:tamponi_test_molecolare r) (:tamponi r))) :by-100k? true :incremental? true :average 7 :last 90})0.7s
Ospedalizzati (attuale)
(plot-regional-data {:measure :totale_ospedalizzati :by-100k? true :incremental? false :average 1 :last 60})0.6s
TI (attuale)
(plot-regional-data {:measure :terapia_intensiva :by-100k? true :incremental? false :average 1 :last 60})0.5s
Ingressi TI
(plot-regional-data {:measure :ingressi_terapia_intensiva :by-100k? true :incremental? false :average 7 :last 60})0.5s
Dati provinciali
(def provincial-data (json/parse-string (slurp "/data_province.json") true))(defn province-data [province-name] (->> provincial-data (filter (= (:denominazione_provincia %) province-name)) (map (select-keys % selected-keys)) distinct))(def provinces {"Milano" "black" "Ravenna" "darkgreen" "Forlì-Cesena" "red" "Ferrara" "gold" "Sondrio" "brown" "Rimini" "skyblue"})(def data-by-province (->> (keys provinces) (map (fn [r] [r (province-data r)])) (into {})))(defn yy [region-name data {:keys [measure incremental? by-100k? average last]}] (let [values (map measure (if incremental? (calculate-delta data) data)) result (cond->> values by-100k? (map (fn [x] (when x (/ x (get pop-100k region-name))))) average (moving-average average) last (take-last last))] result))(defn plot-provincial-data [{:keys [last] :as opts}] {:nextjournal/viewer "plotly"} {:data (mapv (fn [[province-name color]] (let [data (get data-by-province province-name)] {:name province-name :mode "lines" :line {:color color} :x (cond->> (map (comp (apply str %) (take 10 %) :data) data) last (take-last last)) :y (yy province-name data opts)})) provinces) :layout {:xaxis {:autotick true :automargin true}}})0.7s
(plot-provincial-data {:measure :totale_casi :incremental? true :by-100k? true :average 7 :last 60})2.3s