Published
Edited
Apr 1, 2022
Insert cell
Insert cell
// needs colour key and the circles should be accumilitve as the values are added together.
dis = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.style('background','#71a7F5');

svg.append("g").call(xAxis);
svg.append("g").call(yAxis);

const sed = svg.selectAll('circle')
.data(no3)
.enter()
.append('circle')
.attr('r', d => rScale(d.no3_kg_per_yr)) // if r = zero f*** national no data collected
.attr('cx', d => xScale(d.geography_name)+(((width-margin.left-margin.right)/regions.length)/2))
.attr('cy', d => yScale(d.year))
.attr('fill', d => stock_colours[_.indexOf(animals,d.animal)])
.attr('opacity', 0.5)
return svg.node()
}
Insert cell
_.indexOf(animals,'Sheep')
Insert cell
margin = ({top: 50, bottom: 50, left: 75, right: 50})
Insert cell
height = 640
Insert cell
xAxis = g => g
.attr('transform',`translate(0,${height-margin.bottom})`)
.call(d3.axisBottom(xScale ))
Insert cell
yAxis = g => g
.attr('transform', `translate(${margin.left},0)`)
.call(d3.axisLeft(yScale ))
Insert cell
xScale = d3.scaleBand()
.domain([...regions])
.range([margin.left,width-margin.right])
Insert cell
yScale = d3.scalePoint() // .domain(d3.extent(no3.map( d => d.year)))
.domain([...year])
.range([height - margin.bottom,margin.top])
Insert cell
rScale = d3.scaleSqrt()
.domain(d3.extent(no3, d => d.no3_kg_per_yr))
.range([0,30]);
Insert cell
stock_colours=
["#4d4aff", "#dc9e7b", "#fdf515", "#2ab149"]
//['#63dc79','#eaa282','#fdfd4d', '#636807']
Insert cell
Insert cell
canterbury = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.style('background','#71a7F5');

svg.append("g").call(xAxis_canterbury );
svg.append("g").call(yAxis);

const sed = svg.selectAll('circle')
.data(no3_Canterbury)
.enter()
.append('rect')
.attr('width', d => wScale_canterbury(d.no3_kg_per_yr))
.attr('height', 20)
.attr('x', d => xScale_canterbury(d.animal)+((xScale_canterbury.step()/2))-wScale_canterbury(d.no3_kg_per_yr)/2)
.attr('y', d => yScale(d.year)-20) // move it up a little
.attr('fill', d => stock_colours[_.indexOf(animals,d.animal)])
.attr('stroke','#ddd')
return svg.node()
}
Insert cell
xScale_canterbury = d3.scaleBand() //scalePoint()
.domain([...animals])
.range([margin.left,width-margin.right]);
Insert cell
xAxis_canterbury = g => g
.attr('transform',`translate(0,${height-margin.bottom})`)

.call(d3.axisBottom(xScale_canterbury )) //.tickPadding(5))
Insert cell
wScale_canterbury = d3.scaleLinear()
.domain(d3.extent(no3_Canterbury, d => d.no3_kg_per_yr))
.range([0,(width-margin.left-margin.right)/(animals.length)])

Insert cell
Insert cell
chart = {
const root = tree(no3_treeData);

const svg = d3.create("svg");

svg.append("g")
.attr("fill", "none")
.attr("stroke", "#555")
.attr("stroke-opacity", 0.4)
.attr("stroke-width", 1.5)
.selectAll("path")
.data(root.links())
.join("path")
.attr("d", d => `
M${d.target.y},${d.target.x}
C${d.source.y + root.dy / 2},${d.target.x}
${d.source.y + root.dy / 2},${d.source.x}
${d.source.y},${d.source.x}
`);

svg.append("g")
.selectAll("circle")
.data(root.descendants())
.join("circle")
.attr("cx", d => d.y)
.attr("cy", d => d.x)
.attr("fill", d => d.children ? "#555" : "#999")
.attr("r", 2.5);

svg.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("stroke-linejoin", "round")
.attr("stroke-width", 3)
.selectAll("text")
.data(root.descendants())
.join("text")
.attr("x", d => d.y)
.attr("y", d => d.x)
.attr("dy", "0.31em")
.attr("dx", d => d.children ? -6 : 6)
.text(d => d.data.data.geography_name +' '+ d.data.data.animal + ' ' + d.data.data.year)
.filter(d => d.children)
.attr("text-anchor", "end")
.clone(true).lower()
.attr("stroke", "white");

return svg.attr("viewBox", autoBox).node();
}
Insert cell
no3_treeData.data.geography_name
Insert cell
tree = data => {
const root = d3.hierarchy(data).sort((a, b) => d3.descending(a.height, b.height) || d3.ascending(a.data.name, b.data.name));
root.dx = 10;
root.dy = width / (root.height + 1);
return d3.cluster().nodeSize([root.dx, root.dy])(root);
}
Insert cell
function autoBox() {
document.body.appendChild(this);
const {x, y, width, height} = this.getBBox();
document.body.removeChild(this);
return [x, y, width, height];
}
Insert cell
no3_treeData = stratify( no3_hierarchy)
Insert cell
stratify = d3.stratify()
.id( d => d.children )
.parentId( d => d.parent )
Insert cell
nitrateData[nitrateData.length-1]
Insert cell
Insert cell
no3_hierarchy = {

if(nitrateData[nitrateData.length-1].children!='root') {
nitrateData.push({parent: "",
geography_type: "New Zealand",
geography_name: "Aotearoa" ,
children: "root",
animal: "", // not sure if I need these but have them incase structure is needed
year: "1990",
no3_kg_per_yr: 0
})
} // add root node
let no3h = nitrateData.filter( d => {
// d.year=new Date(Date.UTC(d.year, 0, 1)) // can't use "Date" as I am using the year sting in the name hierarchy
d.year=''+d.year // fix the auto format make the year a string
if (d.no3_kg_per_yr==-1) d.no3_kg_per_yr =0 // fix up the NA -1 data to read zero as some regions used 0 and others NA
switch(d.geography_name){
case 'New Zealand':
d.children=d.geography_name+d.animal+d.year
d['parent']='root'
break;

case 'North Island':
case 'South Island':
d.children=d.geography_name+d.animal+d.year
d['parent']='New Zealand'+d.animal+d.year
break;

case "Auckland":
case "Bay of Plenty":
case "Gisborne":
case "Hawke's Bay":
case "Manawatu-Whanganui":
case "Waikato":
case "Wellington":
case "Northland":
case "Taranaki":
d.children = d.geography_name+d.animal+d.year
d.parent = 'North Island'+d.animal+d.year
break;

case "Otago":
case "Southland":
case "Marlborough":
case "Tasman":
case "West Coast":
case "Canterbury":
d.children = d.geography_name+d.animal+d.year
d.parent = 'South Island'+d.animal+d.year
break;
}

return d
})
return no3h
}
Insert cell
md`# table stuff
layout: https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout
https://github.com/observablehq/inputs/blob/main/README.md#table

align, // object of column name to left, right, or center
width = {}, // object of column name to width
layout // "fixed" or "auto"


{layout:'auto'} or {layout:'fixed'}

{
layout: "auto",
rows: Infinity,
sort: "New cases",
reverse: true,
align: {
"Trend": "right",
"New cases": "left"
},

`
Insert cell
Insert cell
viewof res = Table(search,
{ columns: ["geography_name", "animal",'year','parent','children'],
layout:'auto',
align: { 'animal':'center','year':'center'},
width: { 'geography_name':'150px','parent':'200px'}
})
Insert cell
res
Insert cell
Insert cell
no3_Canterbury = no3.filter( d => {
if (d.geography_name=='Canterbury') return d
// { convert date to a string }
})
Insert cell
no3 = nitrateData.filter( d => {
if (d.geography_type=='Region') return d.no3_kg_per_yr!=-1
})
Insert cell
Insert cell
nzNO3 = Table(nitrateData,{columns: ["year", "geography_name", "animal",'no3_kg_per_yr'],sort: "no3_kg_per_yr", reverse: true})
Insert cell
Table(no3,{columns: ["year", "geography_name", "animal",'no3_kg_per_yr'],sort: "no3_kg_per_yr", reverse: true})
Insert cell
Table(no3_Canterbury,{columns: ["year", "geography_name", "animal",'no3_kg_per_yr'],sort: "no3_kg_per_yr", reverse: true})
Insert cell
animals = _.values(_.mapValues(_.uniqBy(nitrateData, 'animal'),'animal'))
Insert cell
year = _.values(_.mapValues(_.uniqBy(nitrateData, 'year'),'year'))
Insert cell
regions = _.values(
_.mapValues(
_.uniqBy( nitrateData.filter( d => { if (d.geography_type=='Region') return d.geography_name }
), 'geography_name'), 'geography_name'))
Insert cell
nitrateData = FileAttachment("nitrate_leaching_fixs.csv").csv({typed: true})
Insert cell
import {Table, Search} from "@observablehq/inputs"
Insert cell
_ = require('lodash')
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