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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more