Published
Edited
Jul 16, 2020
Insert cell
Insert cell
viewof includeCtype = checkbox({label: 'Include Country node type', value: true})
Insert cell
viewof includePtype = checkbox({label: 'Include Publication node type', value: true})
Insert cell
swatches2({color: d3.scaleOrdinal(node_types_list, colors_test)})
Insert cell
Insert cell
Insert cell
chart2 = {
// append the svg object to the body of the page
const svg = d3.create("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
const node = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

const split_data = {};
for (let i = 0; i < dimensions2.length; ++i) {
const next = i < dimensions2.length-1 ? i+1 : i-1;
split_data[dimensions2[i]] = [];
for (const d of data.nodes) {
split_data[dimensions2[i]].push({
"from": +d[dimensions2[i]],
"to": +d[dimensions2[next]]
});
}
}
function addLines(dim, next, data) {
node.append("g")
.selectAll("path")
.data(data)
.enter().append("path")
.attr("d", (d) => paths2[selectedEncoding2](d, dim, next))
.style("stroke", (d) => line_color2[dim](d.from))
.style("fill", "none")
.style("stroke-width", 1.5);
}

for (let i = 0; i < dimensions2.length; ++i) {
const next = i < dimensions2.length-1 ? i+1 : i-1;
addLines(dimensions2[i], dimensions2[next], split_data[dimensions2[i]])
}
// Draw the axis:
node.selectAll("axis")
// For each dimension of the dataset I add a 'g' element:
.data(dimensions2).enter()
.append("g")
// I translate this element to its right position on the x axis
.attr("transform", function(d) { return "translate(" + x2(d) + ")"; })
// And I build the axis with the call function
.each(function(d) { d3.select(this).call(d3.axisLeft().scale(y2[d])); })
// Add axis title
.append("text")
.style("text-anchor", "middle")
.attr("y2", -9)
.text(function(d) { return d; })
.style("fill", "black");
return svg.node();
}
Insert cell
paths2 = { return {
straight_path2: function(d, dim, next) {
return d3.line()([[x2(dim), y2[dim](d.from)], [x2(next), y2[next](d.to)]]);
},
bezier_path2: function(d, dim, next) {
return d3.linkHorizontal()
.x(([x]) => x2)
.y(([, y]) => y2)
({source: [x2(dim), y2[dim](d.from)], target: [x2(next), y2[next](d.to)]})
},
bezier_path_down2: function(d, dim, next) {
const p = d3.path();
p.moveTo(x2(dim), y2[dim](d.from));
p.quadraticCurveTo(x2(dim), y2[next](d.to), x2(next), y2[next](d.to));
return p.toString();
},
bezier_path_up2: function(d, dim, next) {
const p = d3.path();
p.moveTo(x2(dim), y2[dim](d.from));
p.quadraticCurveTo(x2(next), y2[dim](d.from), x2(next), y2[next](d.to));
return p.toString();
}
};
}
Insert cell
Insert cell
iris_data
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
dimensions2 = ["Source","Target","Pais"]
Insert cell
Insert cell
x2 = d3.scalePoint()
.range([0, width])
.padding(1)
.domain(dimensions2);
Insert cell
Insert cell
y2 = {
const axis = {}
for (let i in dimensions2) {
let name = dimensions2[i]
axis[name] = d3.scaleLinear()
.domain( d3.extent(data, function(d) { return +d[name]; }) )
.range([height, 0])
}
return axis;
}
Insert cell
Insert cell
line_color2 = {
const cols = {};
for (let i in dimensions2) {
let name = dimensions2[i]
cols[name] = d3.scaleSequential()
.domain(d3.extent(data.nodes, function(d) { return +d[name]; }))
.interpolator(d3[selectedColor]);
}
return cols;
}
Insert cell
Insert cell
Insert cell
Insert cell
max_month = 12 // from 1 to 12
Insert cell
min_month = 1 // from 1 to 12
Insert cell
preprocess_csv_time = function(csv,min_month,max_month) {

var filtered = [];

csv.forEach(function(row) {
var month = row['Time'].split("-")[1]
var eType = row['eType']
if (["0_emails","1_phone"].includes(eType) & month >= min_month & month <= max_month) {
filtered.push(row)
}
if (!["0_emails","1_phone"].includes(eType)){
filtered.push(row)
}
})
return filtered
}
Insert cell
candidate_graph_n = 5 // from 1 to 5 (candidates)
Insert cell
csvs = {
const csv1 = FileAttachment('Q1.csv')
const csv2 = FileAttachment('Q2.csv')
const csv3 = FileAttachment('Q3.csv')
const csv4 = FileAttachment('Q4.csv')
const csv5 = FileAttachment('Q5.csv')
var csvs = [csv1, csv2, csv3, csv4, csv5]
return csvs
}
Insert cell
csv_ori = d3.csvParse(await csvs[candidate_graph_n-1].text())
Insert cell
selected_edge_types = {
var selected = ["0","1"]
if (includePtype) {
selected.push("4")
}
if (includeCtype) {
selected.push("6")
}
return selected
}
Insert cell
colors = get_n_nominal_colors(3) // run this function again to change colour code
Insert cell
csv = preprocess_csv_time(csv_ori,min_month,max_month)
Insert cell
template_csv = d3.csvParse(await FileAttachment("CGCS-Template.fix.csv").text())
Insert cell
template_graph = csv2graph(preprocess_csv_time(template_csv,min_month,max_month),selected_edge_types)
Insert cell
eType2nodeType = function(eType){

var dict = {'0':'person','1':'person','4':'publication','6':'country'}
return dict[eType]
}
Insert cell
csv2graph = function(csv,selected_edge_types) {
var links = []
var nodes = []
var nodes_number_holder = []
var eTypes = selected_edge_types
for (var row of csv) {
var eType = row.eType.split("_")[0]
if (eTypes.includes(eType)) {
var id_source = row.Source.split("_")[1]
var id_target = row.Target.split("_")[1]
links.push({'source':id_source,'target':id_target,'value':1})
var add_node_s = !(nodes_number_holder.includes(id_source))
var add_node_t = !(nodes_number_holder.includes(id_target))
var groupS = 'person'
var groupT = eType2nodeType(eType)
if (add_node_s){
nodes_number_holder.push(id_source)
nodes.push({'id':id_source,'group':groupS})
}
if (add_node_t){
nodes_number_holder.push(id_target)
nodes.push({'id':id_target,'group':groupT})
}
}
}

return {'links':links,'nodes':nodes}
}
Insert cell
data = csv2graph(csv,selected_edge_types)
Insert cell
node_types_list = {
var nodesT = (template_graph.nodes.map(function(d) {return(d.group)})).filter((x, i, a) => a.indexOf(x) == i)
return (nodesT)
}
Insert cell
colors_test = {
var idx = [0]
if (includePtype) {
idx.push(1)
}
if (includeCtype) {
idx.push(2)
}
var colors_test = colors.filter((x,i) => idx.includes(i))
return colors_test
}
Insert cell
import {get_n_nominal_colors} from "@osvalb/tp-4-carga-de-datos-y-escalas"
Insert cell
import {checkbox} from '@nitaku/checkbox'
Insert cell
function entity(character) {
return `&#${character.charCodeAt(0).toString()};`;
}
Insert cell
drag = simulation => {
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
return d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended);
}
Insert cell
color = {
const scale = d3.scaleOrdinal(node_types_list, colors_test);
return d => scale(d.group);
}
Insert cell
function swatches2({
color,
columns = null,
format = x => x,
swatchSize = 16,
swatchWidth = swatchSize,
swatchHeight = swatchSize,
marginLeft = 0
}) {
const id = DOM.uid().id;

if (columns !== null) return html`<div style="display: flex; align-items: center; margin-left: ${+marginLeft}px; min-height: 40px; font: 13px sans-serif;">
<style>

.${id}-item {
break-inside: avoid;
display: flex;
align-items: center;
padding-bottom: 1px;
}

.${id}-label {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: calc(100% - ${+swatchWidth}px - 0.5em);
}

.${id}-swatch {
width: ${+swatchWidth}px;
height: ${+swatchHeight}px;
margin: 0 0.5em 0 0;
}

</style>
<div style="width: 100%; columns: ${columns};">${color.domain().map(value => {
const label = format(value);
return html`<div class="${id}-item">
<div class="${id}-swatch" style="background:${color(value)};"></div>
<div class="${id}-label" title="${label.replace(/["&]/g, entity)}">${document.createTextNode(label)}</div>
</div>`;
})}
</div>
</div>`;

return html`<div style="display: flex; align-items: center; min-height: 40px; margin-left: ${+marginLeft}px; font: 13px sans-serif;">
<style>

.${id} {
display: inline-flex;
align-items: center;
margin-right: 1em;
}

.${id}::before {
content: "";
width: ${+swatchWidth}px;
height: ${+swatchHeight}px;
margin-right: 0.5em;
background: var(--color);
}

</style>
<div>${color.domain().map(value => html`<span class="${id}" style="--color: ${color(value)}">${document.createTextNode(format(value))}</span>`)}</div>`;
}
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