Public
Edited
Jul 12, 2022
1 fork
Importers
3 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof currentDate = Scrubber(allDates.map(d => dateParseShort(d)), {
format: date =>
date.toLocaleString("es", {
month: "long",
day: "numeric",
year: "numeric"
}),
initial: allDates.length - 45,
autoplay: true,
loop: false,
delay: 100
})
Insert cell
viewof updateLive = {
const btn = html`<button>Cargar últimos datos</button>`;
btn.value = false;
const evt = btn.addEventListener("click", function() {
btn.value = true;
btn.dispatchEvent(new CustomEvent("input"));
btn.setAttribute("disabled", true);
btn.innerText = "Espere unos 2 minutos";
});
invalidation.then(() => btn.removeEventListener("click", evt));
return btn;
}
Insert cell
viewof days = slider({
min: 0,
max: 15,
value: 7,
step: 1,
title: "Ventana Promedio",
description: "Días anteriores incluídos en el promedio"
})
Insert cell
viewof threeshold = slider({
min: 0,
max: 30,
value: 21,
step: 1,
title: "Num. días incompletos",
description: "Después de cuantos días se consideran confiables los datos"
})
Insert cell
viewof attrSelected = select({
options: types_of_dates.map(d => ({ label: datesLabels[d], value: d })),
title: "Fecha a utilizar"
})
Insert cell
vlChart = {
let data = countsByDate.filter(d => d.value > 0);

const maxDateWithValue = new Date(currentDate);
const aWeekBeforeMax = maxDateWithValue - 7 * 24 * 3600000;
const thresholdBeforeMax = maxDateWithValue - threeshold * 24 * 3600000;
data = countsByDate.map(d => ({
...d,
Confiabilidad:
d.key < thresholdBeforeMax
? 1
: (maxDateWithValue - d.key) / (threeshold * 24 * 3600000) / 2
}));

const gridCondition = {
condition: {
test: "+timeFormat(datum.value, '%d') <= 7",
value: []
},
value: [1, 5]
};
const base = vl.markBar({ tooltip: true }).encode(
vl
.x()
.fieldT("key")
.timeUnit("yearmonthdate")
.title(datesLabels[attrSelected])
.axis({
gridDash: gridCondition,
tickCount: "week",
tickDash: gridCondition,
labelAlign: "left",
labelExpr:
"[timeFormat(datum.value, '%d'), +timeFormat(datum.value, '%d') <= 7 ? timeFormat(datum.value, '%b') : '']",
labelOffset: 4,
labelPadding: -24,
tickSize: 30
}),
vl
.y()
.fieldQ("value")
.title("Casos Reportados")
.scale({ domainMin: 0 })
.axis({
tickMinStep: 100,
gridDash: {
condition: {
test: "datum.value % 1000==0",
value: []
},
value: [2, 10]
}
}),
vl
.opacity()
.fieldQ("Confiabilidad")
.scale({ domain: [0, 1], range: [0, 1] })
.legend(
width > 600
? {
format: "%",
symbolFillColor: "steelblue",
symbolStrokeColor: "steelblue"
}
: null
)
);

const bar = base.encode(
vl
.color()
.fieldQ("value")
.title("Casos Reportados")
.legend(width > 600)
.scale({ scheme: "lightgreyteal" })
);

const line = base
.markLine({
color: "firebrick",
size: 3,
interpolate: "basis",
point: { color: "firebrick" }
})
.transform(
vl.filter("datum.value>0"),
vl.window(vl.mean("value").as("rolling_mean")).frame([-days, 0])
)
.encode(vl.y().fieldQ("rolling_mean"));

return vl
.layer(bar, line)
.data(data)
.width(width - (width > 600 ? 200 : 50))
.height(400);
}
Insert cell
maxDate = new Date(countsByDate[countsByDate.length - 1].key)
Insert cell
fmt = {
const fmt = d3.timeFormatDefaultLocale(locale).format;
return fmt("%B %d %Y");
}
Insert cell
types_of_dates = [
"fecha_inicio_sintomas",
"fecha_muerte",
"fecha_reporte_web",
"fecha_recuperado",
"fecha_de_notificaci_n",
"fecha_diagnostico"
]
Insert cell
datesLabels = ({
fecha_inicio_sintomas: "Fecha de Inicio de Síntomas",
fecha_reporte_web: "Fecha Reporte Web",
fecha_de_notificaci_n: "Fecha de Notificación",
fecha_muerte: "Fecha de Muerte",
fecha_diagnostico: "Fecha Diagnóstico",
fecha_recuperado: "Fecha Recuperado"
})
Insert cell
allCountsByDate = {
if (updateLive === "false") return cachedData;
const before = new Date();

const cs = crossfilter(recentData);

cs.groups = {};
cs.dims = {};
for (let tod of types_of_dates) {
cs.dims[tod] = cs.dimension(d => dateParse(d[tod]));
cs.groups[tod] = cs.dims[tod].group();
}
console.log("Groups done", (new Date() - before) / 1000, cs.groups);

const maxDate = dateParse(
recentData[recentData.length - 1].fecha_reporte_web
);
const firstDate = new Date(2020, 2, 6);

let allCounts = {};
for (let date of d3.timeDay.range(
firstDate,
maxDate.getTime() + 24 * 3600000 // Plus one day
)) {
cs.dims.fecha_reporte_web.filter([firstDate, date]);
allCounts[dateFmt(date)] = {};

const maps = {};
for (let tod of types_of_dates) {
maps[tod] = new Map(
cs.groups[tod]
.all()
.filter(d => d.key)
.map(d => [dateFmt(d.key), d.value])
);
// allCounts[dateFmt(date)][tod] = cs.groups[tod]
// .all()
// .filter(d => d.key)
// .map(d => ({ ...d, key: dateFmt(d.key) }));
}
console.log("Maps done", (new Date() - before) / 1000);
allCounts[dateFmt(date)] = [];

for (let [key, value] of maps.fecha_reporte_web) {
const objWithAllDates = { key };
for (let tod of types_of_dates) {
objWithAllDates[tod] = maps[tod].get(key);
}
allCounts[dateFmt(date)].push(objWithAllDates);
}
}
console.log("Crossfilter time ", (new Date() - before) / 1000);

return allCounts;
}
Insert cell
allCountsForCSV = {
let res = [];
for (let fecha_historica in allCountsByDate) {
res = res.concat(
allCountsByDate[fecha_historica].map(d => ({ ...d, fecha_historica }))
);
}
return res;
}
Insert cell
allDates = Object.keys(allCountsByDate)
Insert cell
countsByDate = allCountsByDate[dateFmt(currentDate)].map(d => ({
value: +d[attrSelected],
key: dateParseShort(d.key)
}))
Insert cell
cachedData = {
// const cachedData = await FileAttachment("allCountsByDate_7@1.json")
// .text()
// .then(res => JSON.parse(res))
// .then(allDates => {
// for (let date in allDates) {
// for (let type_of_dates of types_of_dates)
// allDates[date][type_of_dates] = allDates[date][type_of_dates].map(
// d => ((d.key = d.key), d)
// );
// }
// return allDates;
// });

let cachedData = {};
await FileAttachment("allCountsByDate_13.csv")
.csv()
.then(csv => {
csv.forEach(row => {
if (!(row.fecha_historica in cachedData)) {
cachedData[row.fecha_historica] = [];
}
cachedData[row.fecha_historica].push(row);
});
});

return cachedData;
}
Insert cell
recentData[recentData.length - 1]
Insert cell
recentData = {
if (updateLive === "false") return [];
console.log("Downloading recent Data");

const before = new Date();
const generator = loadSocrata(
"https://www.datos.gov.co/resource/gt2j-8ykr.csv",
{
progressive: false
}
);

const { value, done } = await generator.next();
console.log("Got live data", value.length, (new Date() - before) / 1000);

return value;
}
Insert cell
// recentDataCSV = recentData.map(d => (delete d.__i, d))
Insert cell
// viewof selected = navio(recentData)
Insert cell
dateParse = d3.timeParse("%d/%m/%Y %H:%M:%S")
Insert cell
dateFmt = d3.timeFormat("%Y-%m-%d")
Insert cell
dateParseShort = d3.timeParse("%Y-%m-%d")
Insert cell
d3 = require("d3-time-format", "d3-array", "d3-time")
Insert cell
locale = fetch(
"https://unpkg.com/d3-time-format@2/locale/es-MX.json"
).then(res => res.json())
Insert cell
import { vl } from "@vega/vega-lite-api-v5"
Insert cell
import { slider, select } from "@jashkenas/inputs"
Insert cell
import { loadSocrata } from "@john-guerra/socrata-load-multiples-pages"
Insert cell
crossfilter = require("crossfilter2")
Insert cell
import { Scrubber } from "@mbostock/scrubber"
Insert cell
import { navio } from "@john-guerra/navio"
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more