Public
Edited
Feb 9, 2023
1 fork
Insert cell
Insert cell
Insert cell
// dataset = FileAttachment("dataset.json").json()
Insert cell
import {Player} from "@oscar6echo/player"
Insert cell
import { style as faStyle } from "@airbornemint/fontawesome"
Insert cell
//import { select } from "@bartok32/diy-inputs"
Insert cell
a = faStyle({ solid: true })
Insert cell
import { slider} from "@bartok32/diy-inputs"
Insert cell
viewof file2 = Text({label: "File name", value: "dataset.json"})
Insert cell
objectParams2 = ({
Bucket : bucket,
Key : file2
});
Insert cell
data_raw_2 = s3.getObject(objectParams2)
.promise()
.then((json) => json)
Insert cell
dataset = JSON.parse(data_raw_2.Body.toString())
Insert cell
Insert cell
//getComunaData({dataset, comunas_key: ["t.c.olmue", "t.c.nogales"], columns: "inscritos_nuevos", value: "inscritos_nuevos"})
//dataPorComuna1 = getComunaData({dataset, comunas_key: comunaList})
Insert cell
// comunaList // .undefined
Insert cell
// conexion con s3
AWS = require('aws-sdk@2.794.0/dist/aws-sdk-react-native.js')
Insert cell
credentials = AWS.config.credentials =
new AWS.Credentials("AKIAZKMMYM5JRBIQDRPB", "JnKi2ezpw/K1hlxoxGMC4JxE/fbCTic/973hxGwE")
Insert cell
region_aws = AWS.config.region = 'us-east-1'
Insert cell
awsConfig = AWS.config.update({
accessKeyId: "AKIAZKMMYM5JRBIQDRPB",
secretAccessKey: "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",
region: region_aws
});
Insert cell
s3 = {
// call credentials and region here to make sure those are set before creating the S3 object
credentials;
region_aws;
return new AWS.S3({apiVersion: '2006-03-01'})
}
Insert cell
import {Text} from "@observablehq/inputs@426"
Insert cell
viewof bucket = Text({label: "Bucket name", value: "scanner-congreso-contenidos"})
Insert cell
viewof file = Text({label: "File name", value: "padron_rangos_mapa.json"})
Insert cell
objectParams = ({
Bucket : bucket,
Key : file
});
Insert cell
s3.getObject(objectParams)
Insert cell
data_raw_ = s3.getObject(objectParams)
.promise()
.then((json) => json)
Insert cell
function addValue(){
let data = getComunaData({dataset, comunas_key: comunaList2(), columns:["inscritos_total", "contagiados"]})
data.map(x =>{
let a = 100 * x.contagiados / x.inscritos_total
x.value = a.toFixed(2)})
return data.slice()
}
Insert cell
// dataPorComuna = addValue()
dataPorComuna = JSON.parse(data_raw_.Body.toString())
Insert cell
Insert cell
width = 600
Insert cell
Insert cell
dataFiltradaPorComuna = dataPorComuna.filter(data => (data.rango_etario === edad))
Insert cell
dataFiltradaPorComuna[6]
Insert cell
viewof añom2 = slider({
title: "Año",
min: 2012,
max: 2022,
step: 1,
value: 2012,
background: {
type: "double",
colors: ["#b8d551", "#EDEDED"]
}
})
Insert cell
viewof añoNna = slider({
title: "Año",
min: 2012,
max: 2022,
step: 1,
value: 2012,
background: {
type: "double",
colors: ["#b38df0", "#EDEDED"]
}
})
Insert cell
viewof añom2nna = slider({
title: "Año",
min: 2012,
max: 2021,
step: 1,
value: 2012,
background: {
type: "double",
colors: ["#fac72f", "#EDEDED"]
}
})
Insert cell
viewof año1 = Player(año_opciones, {
delay: 1200,
loop: true,
show: { play: true, stop: true }
})
Insert cell
Insert cell
Insert cell
m2 = FileAttachment("comuna_anno@10.json").json()
Insert cell
dataFiltrada = m2.filter(data => (data.anno === añom2))
Insert cell
año_opciones = [...new Set(m2.map(data => data.anno))]
Insert cell
Insert cell
selectorPais = selectDiv_m2()
Insert cell
mapa_metros2 = showMap_m2()
Insert cell
viewof mapa_m2 = map(
dataFiltrada,
m2,
createTooltip,
"Kilómetros cuadrados de áreas verdes", [0,0, 0.5, 1, 1.5, 2, 2.5, 3.0, 3.5],
"m2"
)

//revisar problemas con los trickhesholds y colores.
//disminuir tamaño de la leyenda.
//unificar la escala de medida, con saltos proporcionales.

//hacer saltos proporcionales para los colores.
//min 0 - max 3
Insert cell
Insert cell
proyeccionNna1 = FileAttachment("comuna_anno@10.json").json()
Insert cell
comuna_anno@4.json
Type SQL, then Shift-Enter. Ctrl-space for more options.

Insert cell
dataFiltrada_nna = proyeccionNna1.filter(data => (data.anno === añoNna))
Insert cell
Insert cell
selector_nna = selectDiv_nna()
Insert cell
mapanna = showMap_nna()
Insert cell
viewof mapa_nna = map(
dataFiltrada_nna,
proyeccionNna1,
createTooltip,
"Monto promedio renta por Comuna", [0, 250000, 500000, 750000, 1000000, 1250000, 1500000, 1750000, 2000000],
"proyeccionNna"
)

//min 5 - 25% 2300 - prom 13000 - 75% 13500 - max 181 000
Insert cell
Insert cell
m2PorNna1 = FileAttachment("m2 por nna@1.json").json()
Insert cell
dataFiltrada_m2nna = m2PorNna1.filter(data => (data.año === añom2nna))
Insert cell
Insert cell
selector_m2nna = selectDiv_m2nna()
Insert cell
mapam2nna = showMap_m2nna()
Insert cell
viewof mapa_m2nna = map(
dataFiltrada_m2nna,
m2PorNna1,
createTooltip,
"Metros cuadrados por proyección de nna", [0,0, 10, 20, 30, 40, 50, 60, 70],
"M2 por nna"
)

// min 0 - max 400
Insert cell
map = function map(data, dataColorScale, createTooltip, legendTitle, tickThresholds, maptype){
let {geoObj, mapProjection} = getMapConf(tipoMapa);
const svg = d3.create("svg")
.style("width", "100%")
.style("height", "80%")
.attr("viewBox", function() {
return tipoMapa === 'País' ? "0 200 650 300": "-300 0 1200 750";
})
// Legend
if (data && data.length) {
svg.append("g")
.attr("transform", function() {
return tipoMapa === 'País'? `translate(${width/2 - 60}, ${height - 200})`: `translate(${width/2 - 140}, ${height + 50}) `;
})
.append(() =>
legend({
color: color(dataColorScale, maptype),
title: legendTitle,
tickFormat: ".0f",
width: tipoMapa === 'País'? 200 : 380,
height: tipoMapa === 'País' ? 50 : 64,
titleFontSize: tipoMapa === 'País' ? "7px" : "14px",
titleFontWeight: "200",
tickFontSize: tipoMapa === 'País' ? "5px": "10px",
tickSize: tipoMapa === 'País' ? 8: 20,
tickWidth: tipoMapa === 'País' ? 0.7 : 1,
tickPos: tipoMapa === 'País' ? 4 : 7,
tickThresholds: tickThresholds,
roundedValues: false,
sin_info: true
})
);
}
// Tooltip
if (createTooltip) {
var div = d3.select("body").append("div")
.attr("class", "arrow_box")
.style("opacity", 0);
}
// Mapa
svg.append("g")
.selectAll("path")
.data(geoObj.geometries)
.enter()
.append("path")
.attr("class", "decideChileMap")
.attr("fill", d => map_color(d.properties.canonical_key, data, dataColorScale, tickThresholds, maptype))
.attr("d", d3.geoPath(mapProjection))
.attr('transform', function() {
return tipoMapa === 'País' ? 'rotate(-90 300 300)': null;
})
.on('mouseover', function (d, i) {
svg.selectAll("path")
.attr("fill-opacity", 0.2)
d3.select(this).transition()
.duration('25')
.attr("fill-opacity", 0.8)
//Tooltip
div.html(createTooltip(d, data, maptype))
.style("left", (d3.event.pageX + 20) + "px")
.style("top", (d3.event.pageY + 20) + "px")
.transition()
.duration('25')
.style("opacity", 1) ;
})
.on('mouseout', function (d) {
svg.selectAll("path")
.attr("fill-opacity", 0.8)
d3.select(this).transition()
.duration('25')
//Tooltip
div.transition()
.duration('25')
.style("opacity", 0);
});

// Logo DecideChile
svg.append('image')
.attr('xlink:href', "https://images.squarespace-cdn.com/content/v1/6078e332d6af970bb7b95e6f/1672340132826-T3GAGDEAALAA6MLWYERN/poweredbyunholster.png?format=500w")
.attr("height", function() {
return tipoMapa === 'País'? 27: 47;
})
.attr("transform", function() {
return tipoMapa === 'País'? `translate(${width - 60}, ${height - 160})`: `translate(600, 700) `;
})
return svg.node()
}
Insert cell
titulo = (titulo) =>
{ return html`
<div class="titulo_mapa"> ${titulo}</div>`
}
Insert cell
Insert cell
Insert cell
Insert cell
// topologia = fetch(mapBuildUrl + '/t/base.canonical_key.topo.json').then(r => r.json())
//topologia = FileAttachment("topo2@1.json").json()
Insert cell
viewof file4 = Text({label: "File name", value: "topo2@1.json"})
Insert cell
objectParams4 = ({
Bucket : bucket,
Key : file4
});
Insert cell
s3.getObject(objectParams4)
Insert cell
data_raw_4 = s3.getObject(objectParams4)
.promise()
.then((json) => json)
Insert cell
topologia = JSON.parse(data_raw_4.Body.toString())
Insert cell
//topologiaGS = fetch('https://www.decidechile.cl/data-vis/mapas/comunas/GranSantiago3.json').then(r => r.json())
//topologiaGS = FileAttachment("GranSantiago3.json").json()
Insert cell
viewof file5 = Text({label: "File name", value: "GranSantiago3.json"})
Insert cell
objectParams5 = ({
Bucket : bucket,
Key : file5
});
Insert cell
s3.getObject(objectParams5)
Insert cell
data_raw_5 = s3.getObject(objectParams5)
.promise()
.then((json) => json)
Insert cell
topologiaGS = JSON.parse(data_raw_4.Body.toString())
Insert cell
//comunasPorRegion["Región del Libertador Bernardo O'Higgins"]
Insert cell
Insert cell
Insert cell
// comunasPorDistrito = filterComunasBy('DIS_ELEC')
Insert cell
comunasPorPais = filterComunasBy('País')
Insert cell
comunasPorRegion["Región del Libertador Bernardo O'Higgins"]
Insert cell
// regiones = Object.keys(comunasPorRegion)
regiones = ["Región de Arica y Parinacota", "Región de Tarapacá", "Región de Antofagasta", "Región de Atacama", "Región de Coquimbo", "Región de Valparaíso", "Región Metropolitana de Santiago", "Región del Libertador Bernardo O'Higgins", "Región del Maule", "Región de Ñuble", "Región del Bío-Bío", "Región de La Araucanía", "Región de Los Ríos", "Región de Los Lagos", "Región de Aysén del Gral.Ibañez del Campo", "Región de Magallanes y Antártica Chilena"]
Insert cell
Insert cell
comunasPorPais.undefined
Insert cell
Insert cell
Insert cell
Insert cell
//genres = [...new Set(dataPorComuna.map(data => data.sexo))]
Insert cell
rango_etario = [...new Set(dataPorComuna.map(data => data.rango_etario))]
Insert cell
Insert cell
showMap_m2 = () => {
if (tipoMapa === 'País') {
return html`
<div class="map-container">
${viewof mapa_m2}
</div>`
}
return html`${viewof mapa_m2}`}
Insert cell
showMap_nna = () => {
if (tipoMapa === 'País') {
return html`
<div class="map-container">
${viewof mapa_nna}
</div>`
}
return html`${viewof mapa_nna}`}
Insert cell
showMap_m2nna = () => {
if (tipoMapa === 'País') {
return html`
<div class="map-container">
${viewof mapa_m2nna}
</div>`
}
return html`${viewof mapa_m2nna}`}
Insert cell
selectDiv_m2= () => {
if (tipoMapa === 'Regional')
{ return html`
<div class="grid-container-select">
<div class="item3">${viewof tipoMapa}</div>
<div class="item4">${viewof region}</div>
<div class="item3">${viewof añom2}</div>
</div>
`
}
else
{
return html`
<div class="grid-container-select">
<div class="item3">${viewof tipoMapa}</div>
<div class="item3">${viewof añom2}</div>
</div>`
}
}
Insert cell
selectDiv_nna= () => {
if (tipoMapa === 'Regional')
{ return html`
<div class="grid-container-select">
<div class="item3">${viewof tipoMapa}</div>
<div class="item4">${viewof region}</div>
<div class="item3">${viewof añoNna}</div>
</div>
`
}
else
{
return html`
<div class="grid-container-select">
<div class="item3">${viewof tipoMapa}</div>
<div class="item3">${viewof añoNna}</div>
</div>`
}
}
Insert cell
selectDiv_m2nna= () => {
if (tipoMapa === 'Regional')
{ return html`
<div class="grid-container-select">
<div class="item3">${viewof tipoMapa}</div>
<div class="item4">${viewof region}</div>
<div class="item3">${viewof añom2nna}</div>
</div>
`
}
else
{
return html`
<div class="grid-container-select">
<div class="item3">${viewof tipoMapa}</div>
<div class="item3">${viewof añom2nna}</div>
</div>`
}
}
Insert cell
viewof region = select({
selected: "Región Metropolitana de Santiago",
options: regiones,
onchange: objs => {
d3.select(objs.select)
.style('background', '#EDEDED')
.on('end', () => objs.div.update(objs.select.value));
}
})
Insert cell
viewof tipoMapa = select({
options: [
'País',
'Regional',
// 'Provincial',
// 'Distrito',
]
});
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
//FileAttachment("dataset_exp.json").json()
Insert cell
viewof file3 = Text({label: "File name", value: "dataset_exp.json"})
Insert cell
objectParams3 = ({
Bucket : bucket,
Key : file3
});
Insert cell
s3.getObject(objectParams3)
Insert cell
data_raw_3 = s3.getObject(objectParams3)
.promise()
.then((json) => json)
Insert cell
JSON.parse(data_raw_3.Body.toString())
Insert cell
Insert cell
function color(data, maptype=undefined, val=false, tickThresholds=undefined) {
let bounds = tickThresholds === undefined ? dataBounds(data) : [tickThresholds[0], tickThresholds[tickThresholds.length - 1]]

if (maptype === 'm2') {
let scale = d3.scaleQuantize(bounds, [
"#d1e48f",
"#c9df7a",
"#c0da66",
"#b8d551",
"#b0d03c",
"#a3c42f",
"#8a9a25",
"#92af2a"
]) //get_colors(6, 'blue2', 1, 6))// get_colors(5, 'red'))
if (val) {
return scale(val)
}
return scale
}
if (maptype == 'proyeccionNna') {
let scale = d3.scaleQuantize(bounds, [
"#e0d1f9",
"#d1baf6",
"#c2a4f3",
"#b38df0",
"#a476ed",
"#9560ea",
"#8649e7",
"#7732e4"
])
if (val) {
return scale(val)
}
return scale
}
else {
let scale = d3.scaleQuantize(bounds, [
"#fcdb7a",
"#fbd461",
"#fbce48",
"#fac72f",
"#f9c016",
"#f0b506",
"#d7a305",
"#be8f05"
])
if (val) {
return scale(val)
}
return scale
}
}
Insert cell
Insert cell
getMapConf = (mapType) => {
const geoObj = getGeoObj(mapType);
const mapProjection = projection(geoObj);
return {
geoObj: geoObj,
mapProjection: mapProjection
}
}
Insert cell
getGeoObj = (mapType) => {
const topo = topos[mapType];
return {
type: 'GeometryCollection',
geometries: topo.geometries.map(comuna => {
const mesh = topo.extra? topojson.mesh(topologiaGS, comuna) : topojson.mesh(topologia, comuna);
return {
...mesh,
properties: {
canonical_key: comuna.properties.canonical_key,
centroid: d3.geoCentroid(mesh),
comuna: comuna.properties.comuna
}
}
})
}
}
Insert cell
filterTopologia = (filter, distList) => {
const geometries = topologia.objects.base.geometries
console.log(filter)
if (filter === "Gran Santiago"){
return {
type: 'GeometryCollection',
geometries: topologiaGS.objects.base.geometries,
extra: true
}
}

if (filter === "País"){
return {
type: 'GeometryCollection',
geometries: geometries.filter(
geom => distList.includes(geom.properties.canonical_key))
}
}

return {
type: 'GeometryCollection',
geometries: geometries.filter(
geom => distList[filter].includes(geom.properties.canonical_key))
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
<style>
@import url('${fonts['condensed']['url']}');

/* Grid container select */
.item3 {
grid-area: tipomapa;
min-width: 0;
min-height: 15;
}
.item4 {
grid-area: seleccion;
min-width: 0;
min-height: 15;
}

.item5 {
grid-area: genero;
min-width: 0;
min-height: 15;
}

.item6 {
grid-area: ano;
min-width: 15;
}

.grid-container-select {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
grid-gap: 20px;
}

/* Mapa */

.decideChileMap {
stroke:#FFFFFF;
stroke-width: 0.2;
stroke-linejoin: round;
}

.map-container {
max-height: 750px;
}

/* Tooltip */

.arrow_box {
pointer-events: none;
font-family: ${fonts['default']['family']};
font-size: 13px;
padding: 8px 15px;
position: absolute;
background: #ffffff;
border-radius: 2px;
box-shadow: 0 10px 16px 0 rgba(0,0,0,0.2),8px 6px 15px 0 rgba(0,0,0,0.19);
display: flex;
flex-direction: column;
}

strong {
border-bottom: 1px solid black;
font-family: ${fonts['default']['family']};
padding-bottom: 2px;
justify-content: center;
display: flex;
color: #1A1A1A;
font-weight: 900;
font-size: 13px;
}

.texto-subtitulo {
font-family: ${fonts['condensed']['family']};
color: #1A1A1A;
font-weight: 400;
font-size: 10px;
justify-content: center;
display: flex;
}

.texto-primario {
color: #000000;
font-family: ${fonts['default']['family']};
font-weight: 700;
font-size: 16px;
padding-top: 0px;
justify-content: center;
display: flex;
}

.texto-sin-informacion {
color: #CC0014;
font-family: ${fonts['condensed']['family']};
font-weight: 450;
font-size: 12px;
padding-top: 3px;
justify-content: center;
display: flex;
}

.texto-secundario {
color: #828282;
font-family: ${fonts['condensed']['family']};
font-size: 10px;
font-weight: 400;
justify-content: center;
display: flex;
}
.titulo_mapa {
color: #000000 ;
font-family: ${fonts['default']['family']};
font-weight: 900;
font-size: 24px;
padding-top: 0px;
justify-content: center;
display: flex;
}

</style>

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import {uniqueValid} from "@uwdata/data-utilities"
Insert cell
input2 = (settings = {}, type) => {
if (typeof settings !== "object") {
return "Please provide a value!";
}

const theme = settings.theme ? settings.theme : "default",
initialize =
settings.initialize != undefined
? settings.initialize
: type === "button"
? false
: true,
on =
type == "button" ? "onclick" : type === "select" ? "onchange" : "oninput";

setGlobalStyles(theme);

const objs = {
title: createElement("title", settings.title, theme, settings),
desc: createElement("desc", settings.desc, theme, settings),
output:
type === "slider"
? createElement("output", settings.value, theme, settings)
: type == "checkbox"
? createElement("output", settings.label, theme, settings)
: "",
settings,
value: settings.value
};

objs.additionalElement = settings.additionalElement
? createElement(
settings.additionalElement.name,
settings.additionalElement.value,
theme,
settings
)
: "";

(objs[type] = createElement(type, settings.value, theme, settings)),
(objs.div = createElement(
"div",
[objs.title, objs[type], objs.output, objs.additionalElement, objs.desc],
theme,
settings
));

if (type === "slider") {
objs.div.min = settings.min;
objs.div.max = settings.max;
objs.div.step = settings.step;
}

objs[type][on] = () => {
if (!settings.preventUpdate) {
objs.div.update();
}
if (type === "slider")
objs.progress =
(objs.value - settings.min) / (settings.max - settings.min);
if (settings.utilities) {
for (let [key, func] of Object.entries(settings.utilities)) {
func(settings[key], objs);
}
}
if (settings[on]) settings[on](objs);
};

objs.div.update = (value = objs[type].value || settings.value) => {
value = isNaN(value) ? value : +value;

if (type === "checkbox" && objs.value != false) {
value = false;
} else if (type === "checkbox") {
value = settings.value;
}

objs.value = value;
if (type != "select") {
objs[type].value = value;
}

objs.div.value = objs.value;
if (type != "checkbox" && objs.output) {
objs.output.textContent = objs.value;
}

objs.div.dispatchEvent(new CustomEvent("input", { bubbles: true }));
};

if (settings.preventUpdate) objs.div.update();
if (initialize) {
objs[type][on]();
} else if (!settings.preventUpdate) {
objs.div.update();
}

return objs.div;
}
Insert cell
createElement = (type, text = "", theme = "", settings = "") => {
if (text == undefined) return "";
text = type != "slider" && type != "checkbox" ? text : "";

let typesMapping = {
title: {
tag: "div",
mandatoryAttrs: { class: "title" }
},
button: {
tag: "button",
mandatoryAttrs: {}
},
checkbox: {
tag: "input",
mandatoryAttrs: {
type: "checkbox",
value: settings.value
}
},
select: {
tag: "select",
mandatoryAttrs: {}
},
slider: {
tag: "input",
mandatoryAttrs: {
type: "range",
min: settings.min,
max: settings.max,
step: settings.step,
value: settings.value
}
},
output: {
tag: "span",
mandatoryAttrs: { class: "output" }
},
desc: {
tag: "div",
mandatoryAttrs: { class: "desc" }
},
div: {
tag: "div",
mandatoryAttrs: { class: `input-${theme}` }
},
caret: {
tag: "svg",
mandatoryAttrs: { class: "caret" }
}
};

let el = html`<${typesMapping[type].tag}>${text}</${typesMapping[type].tag}>`;
Object.entries(typesMapping[type].mandatoryAttrs).forEach((d) =>
el.setAttribute(d[0], d[1])
);

if (typeof settings[type + "Attrs"] == "object")
Object.entries(settings[type + "Attrs"]).forEach((d) => {
if (d[0] == "class") el.classList.add(d[1]);
else el.setAttribute(d[0], d[1]);
});

if (typeof settings[type + "Style"] == "object")
Object.entries(settings[type + "Style"]).forEach(
(d) => (el.style[d[0]] = d[1])
);

return el;
}
Insert cell
setGlobalStyles = function (style) {
d3.selectAll(".inputStyles")
.data([style])
.enter()
.append("style")
.attr("class", "inputStyles")
.html(themes);
}
Insert cell
Insert cell
select = (settings = {}) => {
if (
typeof settings.options != "object" ||
Object.keys(settings.options).length == 0
) {
return "Please provide at least one option!";
}

if (Array.isArray(settings.options)) {
settings.options = settings.options.reduce(
(obj, key) => Object.assign(obj, { [key]: key }),
{}
);
}

let options = "";
for (let [key, value] of Object.entries(settings.options)) {
options += `<option ${
key == settings.selected ? "selected" : ""
} value = "${value}">${key}</option>`;
}

settings.value = options;
settings.additionalElement = {
name: "caret",
value: `<path d = 'M0,1.5 6,8.5 12,1.5'>`
};

return input2(settings, "select");
}
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