Public
Edited
Mar 29, 2022
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
graph_width = Math.min(600, width - 100);
Insert cell
Insert cell
akl_mean = {
return mean(data, x => x.density, x => x.land_area);
}
Insert cell
akl_mean_100 = {
return mean(data, x => x.density, x => x.density >= 100 && x.land_area);
}
Insert cell
akl_weigted_mean = {
return mean(data, x => x.density, x => x.population);
}
Insert cell
population = {
var p = 0;
data.forEach(x => p += +x.population);
return p;
}
Insert cell
total_area = {
var p = 0;
data.forEach(x => p += x.land_area);
return p;
}
Insert cell
census_aotea_sq_distance_bins = make_bins(
data,
d => d.distance,
density_type == 'pop' ? d => d.population : d => d.land_area,
d => d.density,
{binCount:25, xMax:25});
Insert cell
// approximate position where the town hall is (centroid of SA1 7005303)
town_hall = [1757165.3473740562, 5920139.208033819];
Insert cell
data = {
var map = {};
var path = d3.geoPath();

census_collection.features.forEach((x) =>
{
// in km
var ID = x.properties.ID;
var c = path.centroid(x.geometry);
var d = 0.001 * Math.hypot(town_hall[0] - c[0], town_hall[1] - c[1]);
map[ID] = d;
});
var d = [];
census_input_data.pop_data.forEach(x => {
// stupid hack because I forgot to include land_area in the data.
// Doesn’t work for units with no population
var area = +x.population / +x.density || 0;
d.push({ distance: map[x.ID], land_area: area, ...x});
});

return d;
}
Insert cell
Insert cell
/// weighted mean function. Return 0 if there are no valid values.
function mean(list, accessor, weightAccessor)
{
var aggr = new meanAggregator(accessor, weightAccessor);
list.forEach(e => aggr.add(e));
return aggr.value();
}
Insert cell
meanAggregator = {
function MeanAggregator(accessor, weightAccessor)
{
this.accessor = accessor || (e => e);
this.weightAccessor = weightAccessor || (e => 1);
this.w = 0;
this.x = 0;
}
MeanAggregator.prototype.value = function() { return this.w ? this.x / this.w : 0; }

MeanAggregator.prototype.add = function(e) {
var ew = +this.weightAccessor(e);
var val = +this.accessor(e);
if (ew == ew && val == val)
{
this.x += val * ew;
this.w += ew;
}
};
return MeanAggregator;
}
Insert cell
/// Make bins, aggregating data while taking into account weights
/// for now we always get the weighted mean of the values per bin
function make_bins(data, xAccessor, weightAccessor, valueAccessor, options)
{
options = {binCount: 10, xMax: +Infinity, ...options};
var xMin = Infinity;
var xMax = -Infinity;
data.forEach(e => {
var x = +xAccessor(e);
if (x == x) {
xMin = Math.min(x, xMin);
xMax = Math.max(x, xMax);
}
});
xMax = Math.min(options.xMax, xMax);
// choose bins
var xStep = (xMax - xMin) / options.binCount;
xStep = Math.pow(10, Math.ceil(Math.log10(xStep)));
if (xStep * options.binCount * 0.3 > xMax - xMin) xStep *= .2;
if (xStep * options.binCount * 0.75 > xMax - xMin) xStep *= .5;
var xInvStep = 1 / xStep;

var xBinMinIx = Math.floor(xMin * xInvStep);
var xBinMaxIx = Math.ceil(xMax * xInvStep);
var bins = Array(xBinMaxIx - xBinMinIx).fill().map((_, i) => ({
x: (i + xBinMinIx) * xStep,
n: 0,
_aggr: new meanAggregator(valueAccessor, weightAccessor)
}));
data.forEach(e => {
var x = xAccessor(e);
var x_bin = Math.floor((x - xMin) * xInvStep);
if (x < options.xMax)
{
var bin = bins[x_bin];
bin.n += 1;
bin._aggr.add(e);
}
});

bins.forEach(bin => {
bin.value = bin._aggr.value();
bin.weight = bin._aggr.w;
});
return bins;
}
Insert cell
Insert cell
import { census_input_data, census_collection, param }
with {sa_type as sa_type}
from "@roelandschoukens/mode-share-map"
Insert cell
d3 = require("d3")
Insert cell
VegaLite = require('@observablehq/vega-lite')
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