Public
Edited
Sep 20, 2023
1 fork
Insert cell
Insert cell
iris = require('@observablehq/iris')
Insert cell
import {Wrangler, op} from "@observablehq/data-wrangler"
Insert cell
Wrangler(iris)
Insert cell
avgPetalLength = aq.from(iris)
.select('petalLength','species')
.groupby('species')
.rollup({mean:d => op.mean(d["petalLength"])})
.objects() // Uncomment to return an array of objects
Insert cell
avgPetalWidth = aq.from(iris)
.select('petalWidth','species')
.groupby('species')
.rollup({mean:d => op.mean(d["petalWidth"])})
.objects() // Uncomment to return an array of objects
Insert cell
data = {

let results = [];

avgPetalLength.forEach(function(d) {

console.log("mean",d);
//new prop and delete old
d.avgPetalLen = d.mean;
delete d.mean;


var result = avgPetalWidth.filter(function(s) { //find matching data (for d)
return s.species === d.species;
});

d.avgPetalWidth = result[0].mean

results.push(d)

});

return results;

}
Insert cell
Insert cell
{

const list = d3.create('ul'); // create node <ul>

list
.selectAll().data(data) //select all onj in data
.enter().append('li'); //append li for each obj in array (end chain;)

list.selectAll('li').text(d=>d.species);

return list.node();
}
Insert cell
{

const height = 400; //container h
const margin = 30; //space around graphics

const svg = d3.create('svg')
.attr('width', width) // width is global - document.windowWidth or window.innerWidth
.attr('height', height + margin*2);

const chart = svg.append('g')
.attr('transform', 'translate('+margin+','+margin+')'); //add margin on top, left corner

const maxY = Math.round(d3.max(data, d=>d.avgPetalLen));

//d3 linear scale - map dimensions to values in data
const yScale = d3.scaleLinear()
.range([height, 0])
.domain([0, maxY ])


const xScale = d3.scaleBand()
.range([0, width])
.padding(.5) //space between bars
.domain(data.map(d=>d.species))

//draws y axis
chart.append('g')
.call(
d3.axisLeft(yScale)
.tickFormat(function(d){
d3.select(this)
.attr("font-weight", "bold")
.attr("font-size", "14px")
return d;
})
)//apply scale
.append("text") //y axis label
.attr('transform', "rotate(-90)") //rotate label
.attr("y", 10)
.attr("dy", 10) //line along axis
.attr("text-anchor", "end")
.attr("fill", 'black')
.attr("font-weight", "bold")
.attr("font-size", "18px")
.text("CM");


//draw x axis
chart.append('g')
.attr('transform', 'translate(0, '+ height+')') //moe x axis line
.call(d3.axisBottom(xScale)) //labels
.attr("font-size", 18);


// Define the div for the tooltip
const tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.attr('position', 'absolute')
.style("opacity", 0);

//event to make tooltip follow mouse - comment out if using fixed tooltip
window.onmousemove = function (e) {
const x = (e.clientX - 25) + 'px', y = (e.clientY - 25) + 'px';
tooltip.style("left", x).style("top", y);
};


//colors
const colorScale = d3.scaleOrdinal(d3.schemeCategory10)
//const colorScale = d3.scaleOrdinal().range(["#ca0020","#f4a582","#d5d5d5","#92c5de","#0571b0"]);


chart.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar") //assign class - style - can override style attributes
.attr("x", d=>xScale(d.species))
.attr("y", d=>yScale(d.avgPetalLen))
.attr("width", xScale.bandwidth())
.attr("height", d=> height-yScale(d.avgPetalLen) )
.attr("fill", d=>colorScale(d))
.on("mouseover", function(event, d){
tooltip.transition()
.duration(200)
.style("opacity", 1);
tooltip.html(d3.format('.2')(d.avgPetalLen) + " CM");

})
.on("mouseout", function(event, d){
tooltip.transition()
.duration(200)
.style("opacity", 0);
});

//add title
svg.append("text")
.attr("transform", "translate(0,0)") //move to x,y
.attr("x", 150) //place at x
.attr("y", 50) //place at y
.attr("font-size", "24px")
.text("Iris Petal Length")
return svg.node()
}
Insert cell
<style>
.bar:hover{ opacity: .5}
.tooltip{
position: absolute; padding: "20px"; background-color: #ececec; opacity: 0 !important!;
}
</style>
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