Published
Edited
Sep 3, 2019
Insert cell
Insert cell
md`## Background
Data Source: https://www.datos.gov.co/Estad-sticas-Nacionales/Suicidios-seg-n-edad-2015-entre-hombres-y-mujeres/hi7p-qygt

ATTRIBUTE| TYPE | CLASSIFICATION |DESCRIPTION| POSSIBLE VALUES
--------|--------|-------------------|-----------|-----------
Age Group| Categorical | NaN | Age group of people| (10-14), (15-17)
Men|Ordered| Quantitative with a sequential order|Initial month in which data recording took place| January, March, August ...
Men %| Ordered| Ordinal with a cyclic order| Initial month in which data recording took place| February, June, October ...
Rate Men| Ordered | Ordinal with a sequential order| Year in which data recording took place | 2011,2012,...,2019
Women| Ordered | Quantitative with a sequential order| percentage of unemployment according to gender in a certain period of time | 15.7, 7.1, 11.4 ...
Women %| Ordered| Ordinal with a cyclic order| Initial month in which data recording took place| February, June, October ...
Rate Women| Ordered | Ordinal with a sequential order| Year in which data recording took place | 2011,2012,...,2019
Total| Ordered | Ordinal with a sequential order| Year in which data recording took place | 2011,2012,...,2019
Total %| Ordered | Ordinal with a sequential order| Year in which data recording took place | 2011,2012,...,2019
Total Rate| Ordered | Ordinal with a sequential order| Year in which data recording took place | 2011,2012,...,2019
`
Insert cell
Insert cell
{
const target = html`
<style>
.chart {
font-family: sans-serif;
}
.chart-footer {
font-style: italic;
font-size: 10pt;
color: #aaa;
}
</style>

<div class="chart">
<h2>Presupuesto por tipo de rubro</h2>
<div>Los rubros de funcionamiento son los más grandes</div>
<div id="chart"></div>
<div class="chart-footer">By <a href="https://johnguerra.co">John Alexis Guerra Gómez</a>.
<br>
<strong>Source</strong>: <a href="">My data source</a>
</div>
</div>`;
const
width = 500,
height = 500,
svg = d3.select(target).select("#chart")
.append("svg")
.attr("width", width)
.attr("height", height);
const margin = ({top: 20, right: 30, bottom: 30, left: 200}),
iwidth = width - margin.left - margin.right,
iheight = height - margin.top - margin.bottom;
const gBase = svg.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
gBase.append("text")
.attr("class", "tooltip")
.attr("x", -100)
.style("fill", "black")
.style("stroke", "black")
.text("");
const x = d3.scaleSqrt()
.domain([0, d3.max(data, d => d["APORTE NACIONAL"]) ])
.range([0, iwidth])
.nice();
console.log("xdomain", x.domain());
const y = d3.scalePoint()
.domain(d3.set(data.map(d => d["CONCEPTO2"])).values())
.range([iheight, 0])
.padding(0.5);
gBase.append("g")
.call(d3.axisBottom(x).tickFormat(d3.format("$.2s")))
.attr("transform", `translate(0, ${iheight})`);

gBase.append("g")
.call(d3
.axisLeft(y)
);
function onMouseOver(d) {
d3.select(this)
.style("fill", "firebrick");
gBase.select(".tooltip")
.attr("x", d3.mouse(this)[0])
.attr("y", d3.mouse(this)[1] + 20)
.text(d.CONCEPTO1);
console.log("mouseover", d3.mouse(this));
}
function onMouseOut(d) {
d3.select(this)
.style("fill", "#777");
gBase.select(".tooltip")
.attr("x", -100)
.text("");
console.log(d, d3.event);
}
gBase.selectAll(".points")
.data(data)
.join("circle")
.on("mouseover", onMouseOver)
.on("mouseout", onMouseOut)
.attr("class", "points")
.attr("cx", d => x(d["APORTE NACIONAL"]) )
.attr("cy", d => y(d["CONCEPTO2"]) )
.attr("r", 5 )
.style("opacity", 0.5)
.style("fill", "#777");

return target;
}
Insert cell
congresoAgrupado = {
return d3.nest()
.key(d => d.Nivel2)
.rollup( leaves => ({
leaves,
sum:d3.sum(leaves, d=>d["TOTAL"] ),
numLeaves: leaves.length
}) )
.entries(data)
.sort( (a,b) => d3.ascending(a.value.sum, b.value.sum));
}

Insert cell
{
const target = html`
<style>
.chart {
font-family: sans-serif;
}
.chart-footer {
font-style: italic;
font-size: 10pt;
color: #aaa;
}
</style>

<div class="chart">
<h2>Gastos Nivel 2</h2>
<div>Estos son los gastos agrupando por Nivel 2</div>
<div id="chart"></div>
<div class="chart-footer">By <a href="https://johnguerra.co">John Alexis Guerra Gómez</a>.
<br>
<strong>Source</strong>: <a href="">My data source</a>
</div>
</div>`;
const
width = 800,
height = 500,
svg = d3.select(target).select("#chart")
.append("svg")
.attr("width", width)
.attr("height", height);
const margin = ({top: 20, right: 30, bottom: 30, left: 200}),
iwidth = width - margin.left - margin.right,
iheight = height - margin.top - margin.bottom;
const gBase = svg.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
gBase.append("text")
.attr("class", "tooltip")
.attr("x", -100)
.style("fill", "black")
.style("stroke", "black")
.text("");
const x = d3.scaleSqrt()
.domain([0, d3.max(congresoAgrupado, d => d.value.sum) ])
.range([0, iwidth])
.nice();
console.log("xdomain", x.domain());
const y = d3.scaleBand()
.domain(d3.set(congresoAgrupado.map(d => d.key)).values())
.range([iheight, 0])
.padding(0.3);
gBase.append("g")
.call(d3.axisBottom(x).tickFormat(d3.format("$.2s")))
.attr("transform", `translate(0, ${iheight})`);

gBase.append("g")
.call(d3
.axisLeft(y)
);
function onMouseOver(d) {
d3.select(this)
.style("fill", "firebrick");
gBase.select(".tooltip")
.attr("x", d3.mouse(this)[0])
.attr("y", d3.mouse(this)[1] + 20)
.text(d.CONCEPTO1);
console.log("mouseover", d3.mouse(this));
}
function onMouseOut(d) {
d3.select(this)
.style("fill", "#777");
gBase.select(".tooltip")
.attr("x", -100)
.text("");
console.log(d, d3.event);
}
gBase.selectAll(".item")
.data(congresoAgrupado)
.join("rect")
.on("mouseover", onMouseOver)
.on("mouseout", onMouseOut)
.attr("class", "item")
.attr("x", 0 )
.attr("y", d => y(d.key) )
.attr("width", d => x(d.value.sum ) )
.attr("height", y.bandwidth() )
.style("opacity", 0.5)
.style("fill", "#777");

return target;
}
Insert cell
{
const target = html`
<style>
.chart {
font-family: sans-serif;
}
.chart-footer {
font-style: italic;
font-size: 10pt;
color: #aaa;
}
</style>

<div class="chart">
<h2>Gastos Nivel 2</h2>
<div>Estos son los gastos agrupando por Nivel 2</div>
<div id="chart"></div>
<div class="chart-footer">By <a href="https://johnguerra.co">John Alexis Guerra Gómez</a>.
<br>
<strong>Source</strong>: <a href="">My data source</a>
</div>
</div>`;
const
width = 800,
height = 500,
svg = d3.select(target).select("#chart")
.append("svg")
.attr("width", width)
.attr("height", height);
const margin = ({top: 20, right: 30, bottom: 200, left: 50}),
iwidth = width - margin.left - margin.right,
iheight = height - margin.top - margin.bottom;
const gBase = svg.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
gBase.append("text")
.attr("class", "tooltip")
.attr("x", -100)
.style("fill", "black")
.style("stroke", "black")
.text("");
const y = d3.scaleSqrt()
.domain([0, d3.max(congresoAgrupado, d => d.value.sum) ])
.range([iheight, 0])
.nice();
const x = d3.scaleBand()
.domain(d3.set(congresoAgrupado.map(d => d.key)).values())
.range([0, iwidth])
.padding(0.3);
gBase.append("g")
.call(d3.axisBottom(x))
.attr("transform", `translate(0, ${iheight})`)
.selectAll(".tick text") // Rotate the x axis labels 45 deg
.attr("text-anchor", "end")
.attr("transform", "rotate(-45)");

gBase.append("g")
.call(d3
.axisLeft(y).tickFormat(d3.format("$.2s"))
);
function onMouseOver(d) {
d3.select(this)
.style("fill", "firebrick");
gBase.select(".tooltip")
.attr("x", d3.mouse(this)[0])
.attr("y", d3.mouse(this)[1] + 20)
.text(d.CONCEPTO1);
console.log("mouseover", d3.mouse(this));
}
function onMouseOut(d) {
d3.select(this)
.style("fill", "#777");
gBase.select(".tooltip")
.attr("x", -100)
.text("");
console.log(d, d3.event);
}
gBase.selectAll(".item")
.data(congresoAgrupado)
.join("rect")
.on("mouseover", onMouseOver)
.on("mouseout", onMouseOut)
.attr("class", "item")
.attr("y", d => y(d.value.sum ) )
.attr("x", d => x(d.key) )
.attr("height", d => iheight - y(d.value.sum ) )
.attr("width", x.bandwidth() )
.style("opacity", 0.5)
.style("fill", "#777");

return target;
}
Insert cell
{
const target = html`
<style>
.chart {
font-family: sans-serif;
}
.chart-footer {
font-style: italic;
font-size: 10pt;
color: #aaa;
}
</style>

<div class="chart">
<h2>Presupuesto por tipo de rubro</h2>
<div>Los rubros de funcionamiento son los más grandes. Con un poco de jitter para distribuir los puntos</div>
<div id="chart"></div>
<div class="chart-footer">By <a href="https://johnguerra.co">John Alexis Guerra Gómez</a>.
<br>
<strong>Source</strong>: <a href="">My data source</a>
</div>
</div>`;
const
width = 800,
height = 500,
svg = d3.select(target).select("#chart")
.append("svg")
.attr("width", width)
.attr("height", height);
const margin = ({top: 20, right: 30, bottom: 30, left: 200}),
iwidth = width - margin.left - margin.right,
iheight = height - margin.top - margin.bottom;
const gBase = svg.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
gBase.append("text")
.attr("class", "tooltip")
.attr("x", -100)
.style("fill", "black")
.style("stroke", "black")
.text("");
const x = d3.scaleSqrt()
.domain([0, d3.max(data, d => d["APORTE NACIONAL"]) ])
.range([0, iwidth])
.nice();
const y = d3.scalePoint()
.domain(d3.set(data.map(d => d["CONCEPTO2"])).values())
.range([iheight, 0])
.padding(0.5);
const color = d3.scaleOrdinal(d3.schemeAccent);
gBase.append("g")
.call(d3.axisBottom(x).tickFormat(d3.format("$.2s")))
.attr("transform", `translate(0, ${iheight})`);

gBase.append("g")
.call(d3
.axisLeft(y)
);
function onMouseOver(d) {
d3.select(this)
.style("fill", "firebrick");
gBase.select(".tooltip")
.attr("x", d3.mouse(this)[0])
.attr("y", d3.mouse(this)[1] + 20)
.text(d.CONCEPTO1);
console.log("mouseover", d3.mouse(this));
}
function onMouseOut(d) {
d3.select(this)
.style("fill", "#777");
gBase.select(".tooltip")
.attr("x", -100)
.text("");
console.log(d, d3.event);
}
gBase.selectAll(".points")
.data(data)
.join("circle")
.on("mouseover", onMouseOver)
.on("mouseout", onMouseOut)
.attr("class", "points")
.attr("cx", d => x(d["APORTE NACIONAL"]) )
.attr("cy", d => y(d["CONCEPTO2"]) + (Math.random()*100-50) )
.attr("r", 3 )
.style("opacity", 0.3)
.style("fill", d => color(d["CONCEPTO2"]) );

return target;
}
Insert cell
angleRadiusAxis = function(cx, cy, r, angle, innerRadius, outerRadius, ticks = 3){
return function(sel) {
console.log("angleAxis", sel);
const tickValues = d3.range(innerRadius, outerRadius, (outerRadius-innerRadius)/(ticks+1));
sel.selectAll("circle.tick")
.data(tickValues)
.join("circle")
.attr("class", "tick")
.style("fill", "none")
.style("stroke", "#ccc")
.attr("cx", cx)
.attr("cy", cy)
.attr("r", d => d);
sel.selectAll("text.tickr")
.data(tickValues)
.join("text")
.attr("class", "tickr")
.style("font-size", "8pt")
.style("text-anchor", "middle")
.attr("x", cx)
.attr("y", d => cy - d -1)
.text(d => d3.format("$.2s")(r.invert(d)) );
sel.selectAll("text.tickA")
.data(angle.domain())
.join("text")
.attr("class", "tickA")
.style("font-size", "8pt")
.style("text-anchor", "middle")
.attr("x", d=> cx+ outerRadius*Math.cos(angle(d)))
.attr("y", d=> cy+ outerRadius*Math.sin(angle(d)))
.text(d => d);

sel.selectAll("line.tickA")
.data(angle.domain())
.join("line")
.attr("class", "tickA")
.style("stroke", "black")
.attr("x1", d=> cx+ innerRadius*Math.cos(angle(d)))
.attr("y1", d=> cy+ innerRadius*Math.sin(angle(d)))
.attr("x2", d=> cx+ (innerRadius-5)*Math.cos(angle(d)))
.attr("y2", d=> cy+ (innerRadius-5)*Math.sin(angle(d)))
}
}
Insert cell
{
const target = html`
<style>
.chart {
font-family: sans-serif;
}
.chart-footer {
font-style: italic;
font-size: 10pt;
color: #aaa;
}
</style>

<div class="chart">
<h2>Presupuesto por tipo de rubro</h2>
<div>Los rubros de funcionamiento son los más grandes. En un diagrama radial</div>
<div id="chart"></div>
<div class="chart-footer">By <a href="https://johnguerra.co">John Alexis Guerra Gómez</a>.
<br>
<strong>Source</strong>: <a href="">My data source</a>
</div>
</div>`;
const
width = 500,
height = 500,
innerRadius = 50,
outerRadius = 200,
svg = d3.select(target).select("#chart")
.append("svg")
.attr("width", width)
.attr("height", height);
const margin = ({top: 0, right: 0, bottom: 0, left: 0}),
iwidth = width - margin.left - margin.right,
iheight = height - margin.top - margin.bottom;
const gBase = svg.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
gBase.append("text")
.attr("class", "tooltip")
.attr("x", -100)
.style("fill", "black")
.style("stroke", "black")
.text("");
const r = d3.scaleSqrt()
.domain([0, d3.max(data, d => d["APORTE NACIONAL"]) ])
.range([innerRadius, outerRadius])
.nice();
const angle = d3.scalePoint()
.domain(d3.set(data.map(d => d["CONCEPTO2"])).values())
.range([0, 2*Math.PI])
.padding(0.5);
const color = d3.scaleOrdinal(d3.schemeAccent);
gBase.append("g")
.call(angleRadiusAxis(iwidth/2, iheight/2, r, angle, innerRadius, outerRadius));
function onMouseOver(d) {
d3.select(this)
.style("fill", "firebrick");
gBase.select(".tooltip")
.attr("x", d3.mouse(this)[0])
.attr("y", d3.mouse(this)[1] + 20)
.text(d.CONCEPTO1);
console.log("mouseover", d3.mouse(this));
}
function onMouseOut(d) {
d3.select(this)
.style("fill", "#777");
gBase.select(".tooltip")
.attr("x", -100)
.text("");
console.log(d, d3.event);
}
gBase.selectAll(".points")
.data(data)
.join("circle")
.on("mouseover", onMouseOver)
.on("mouseout", onMouseOut)
.attr("class", "points")
.attr("cx", d => {
d.jitter = Math.PI/2*Math.random()-Math.PI/4;
return iwidth/2 + r(d["APORTE NACIONAL"])*Math.cos(angle(d["CONCEPTO2"]) + d.jitter);
})
.attr("cy", d => iheight/2 + r(d["APORTE NACIONAL"])*Math.sin(angle(d["CONCEPTO2"]) + d.jitter))
.attr("r", 2 )
.style("opacity", 0.3)
.style("fill", d => color(d["CONCEPTO2"]));

return target;
}
Insert cell
data = d3.csv("https://raw.githubusercontent.com/john-guerra/presupuestoColombia/master/PresupuestoGeneralDeLaNacionColombia2020.csv", d3.autoType)
.then(data => {
data.forEach(d => {
if (d['APORTE NACIONAL'])
d["APORTE NACIONAL"] = +(d["APORTE NACIONAL"].replace(/,/g, ""));
if (d['TOTAL'])
d["TOTAL"] = +(d["TOTAL"].replace(/,/g, ""));
});
return data;
});
Insert cell

// {
// // Navio
// const target = html`<div style="overflow:scroll"></div>`;
// const nv = navio(target, 600);
// nv.data(rawData);
// nv.addAllAttribs();
// nv.update();
// return target;
// }
Insert cell
Insert cell
d3 = require("d3@5")
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