Public
Edited
Nov 21, 2022
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
/*
chartLegend = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width - 0, legendHeight])
svg.select('#legendArea')
.append('svg')
.attr('class', 'legend')
.attr('height', legendHeight)
.attr('width', width)
.style('fill', "black")
.style('font-weight', 550)
var legend = svg.append("g")
.classed("legend", true)
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "end")
.selectAll("g.legend")
.data(keys.slice().reverse())
.enter().append("g")
.classed("legend", true)
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; })
legend.append("rect")
.classed("legend", true)
.style("stroke-width", "1.5")
.style("stroke", "#383838")
.attr("rx", "4")
.attr("x", width - 19 - 25)
.attr("width", 19)
.attr("height", 19)
.attr("fill", zScale)
.on("click", function(d, i){ //changed from d3@v5 to d3@v6
console.log("click legend element:");console.log(i);
sortByTaxon(i);
})
.on("mouseover", function(d){
d3.select(this).style("cursor", "pointer")
})
legend.append("text")
.attr("x", width - 24 - 25 )
.attr("y", 9.5)
.attr("dy", "0.32em")
.style("font-family", "sans-serif")
.style("font-size", "10px")
.text(function(d) { return d; });
return svg.node()
}
*/
Insert cell
Insert cell
heightInner = 60
Insert cell
widthInner = 190
Insert cell
data3
Insert cell
sortByTaxon = function(taxon) {
console.log("taxon:");console.log(taxon);
//data3.map(function(d){
// //console.log("d:");console.log(d);
// return d.values.sort(function(a, b) { return b[taxon] - a[taxon]; });
//});
var sorted = data3.sort(function(a, b) { return b[taxon] - a[taxon]; });
chart.updateData(sorted);
}

Insert cell
/*xScale = d3.scaleBand()
.range([0, width - margin.right])
.round(false)
.paddingInner(0.1)
.paddingOuter(0.1)
.align(0.1); */
Insert cell
/*yScale = d3.scaleLinear()
.rangeRound([height - margin.bottom, 0]);*/
Insert cell
/*zScale = d3.scaleOrdinal()
.range(fillColors);*/
Insert cell
margin = ({top: 30, right: 50, bottom: 80, left: 50});
Insert cell
marginInner = ({top: 10, right: 10, bottom: 40, left: 25});
Insert cell
height = 250
Insert cell
data = d3.tsvParse(await FileAttachment("otu_table_final_normalized_L6.txt").text())
Insert cell
Insert cell
data1 = computeTotalAndSort(data);
Insert cell
Insert cell
md`We will only keep the most abundant 20 taxa for clarity sake - and also limitation of colors downstream`
Insert cell
data2 = data1.slice(0,20);
Insert cell
md`We then transform the data to make it compatible with the d3 bar chart syntax`
Insert cell
data3 = processDataForBarChart(data2)
Insert cell
md`Store taxa names (i.e. identifiers of each bar) in keys array`
Insert cell
keys = data3.columns.slice(1);
Insert cell
md`At this point, we will load the metadata (i.e. mapping file)`
Insert cell
mapping = d3.tsvParse(await FileAttachment("mapping_file.tsv").text())
Insert cell
merged = merge(data3, mapping, "Sample", "SampleID")
Insert cell
Insert cell
merged2 = d3.groups(merged, d => d.Treatment)
Insert cell
merged3 = convertD3V6ToD3V5(merged2)
Insert cell
/* function to convert new data structure returned by d3V6's d3.groups function to older d3V5 esque data structures.*/
function convertD3V6ToD3V5(merged){
let arrayOfObjects = []
for(let i=0; i<merged.length; i++) {
let object = {"key" : merged[i][0]}
for(let j=0; j<merged.length; j++) {
object["values"] = merged[i][1]
}
arrayOfObjects.push(object)
}
return arrayOfObjects;
}
Insert cell
/* Simple merge function */
function merge(left, right, leftKey, rightKey){ //data, mapping, sampleID, #sampleID
let merged = [];
for(let i=0; i<left.length; i++) {
merged.push({
...left[i],
...(right.find((itmInner) => itmInner[rightKey] === left[i][leftKey]))}
);
}
return merged;
}
Insert cell
function processDataForBarChart(data){
// Get sample names and remove unwanted keys;
var sampleNames = Object.keys(data[0]);
sampleNames.splice( sampleNames.indexOf('Taxon'), 1 )
sampleNames.splice( sampleNames.indexOf('total'), 1 )

var data2 = new Array(sampleNames.length);
var taxa_list = {};
// loop per sampleNames.
for(var k=0; k<sampleNames.length; k++){
var currSample = sampleNames[k];
var newElement = {};
newElement['Sample'] = currSample;

for(var i=0; i<data.length; i++){
var abundance = ((data[i][currSample]) * 100 / 100).toFixed(2);
var taxon = data[i]['Taxon'];
taxa_list[taxon] = 1;
newElement[taxon] = abundance;
}
data2[k] = newElement;
}
taxa_list = Object.keys(taxa_list);
taxa_list.unshift("Taxon");
//console.log("taxa_list:");
//console.log(taxa_list);
data2['columns'] = taxa_list;
var columns = taxa_list;
// add total and columns
for(var key in data2){
if(key != 'columns'){
var curr_obj = data2[key];
for (var i = 1, t = 0; i < columns.length; ++i){
t += curr_obj[columns[i]] = +curr_obj[columns[i]];
}
data2[key]['total'] = t;
}
}
data2.sort(function(a, b) { return b.total - a.total; });
return data2;
}
Insert cell
fillColors = [
"#0000CD", "#00FF00", "#FF0000", "#808080", "#000000", "#B22222", "#DAA520",
"#DDA0DD", "#FF00FF", "#00FFFF", "#4682B4", "#E6E6FA", "#FF8C00", "#80008B", "#8FBC8F",
"#00BFFF", "#FFFF00", "#808000", "#FFCCCC", "#FFE5CC", "#FFFFCC", "#E5FFCC", "#CCFFCC"]
Insert cell
d3 = require("d3@6")
Insert cell
import {slider} from "@jashkenas/inputs"
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